home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / Drtf / DRichViewNu.cpp < prev    next >
Text File  |  1996-07-05  |  93KB  |  3,476 lines

  1. // DRichView.cpp
  2. // d.g.gilbert
  3.  
  4.  
  5. #include "Dvibrant.h"
  6. #include "DWindow.h"
  7. #include "DPanel.h"
  8. #include "DControl.h"
  9. #include "DFile.h"
  10. #include "DFindDlog.h"
  11. #include "DList.h"
  12. #include "DUtil.h"
  13. #include "DDialogText.h"
  14. #include "DViewCentral.h"
  15.  
  16. #include "DDrawPICT.h"
  17.  
  18. #include "DRichStyle.h"
  19. #include "DRichMoreStyle.h"
  20. #include "DRichViewNu.h"
  21. #include "DRTFHandler.h"
  22. #include "DPICTHandler.h"
  23. #include "DHTMLHandler.h"
  24. #include "DGIFHandler.h"
  25.  
  26. #include "DIconLib.h"
  27. #include "DIcons.h"
  28.  
  29.  
  30. extern DDrawPict* gDrawPict; 
  31.  
  32. static Boolean gNotInitted = true;
  33.  
  34. #ifdef DBUG
  35. #define Debug(x)  fprintf(stderr,x)
  36. #define Debug1(x,y)  fprintf(stderr,x,y);
  37. #else
  38. #define Debug(x) 
  39. #define Debug1(x,y)
  40. #endif
  41.  
  42. enum {
  43.     chPictTag = 26,
  44.     MAXFONTS  = 32
  45.     };
  46.  
  47. static struct fontheights {
  48.   Nlm_FonT  font;
  49.   short          height;
  50.     } gFontHeights[MAXFONTS];
  51.  
  52. extern "C" Nlm_Boolean Nlm_DoClick (Nlm_GraphiC a, Nlm_PoinT pt); // vibutils.c
  53.  
  54. //short DRichView::GetFontHeight(Nlm_FonT font)
  55. static short GetFontHeight(Nlm_FonT font)
  56. {
  57.             // Returns the pixel height of a font, caching for quicker access
  58.   short  height, i;
  59.   height = 0;
  60.   i = 0;
  61.   while (i < MAXFONTS && gFontHeights[i].font != font
  62.          && gFontHeights[i].font != NULL)
  63.             i++;
  64.   if (gFontHeights[i].font == font) 
  65.     return gFontHeights[i].height;
  66.     else {
  67.     Nlm_SelectFont(font);
  68.     height = Nlm_LineHeight();
  69.     if (i < MAXFONTS) {
  70.       gFontHeights[i].font = font;
  71.       gFontHeights[i].height = height;
  72.         }
  73.        return height;
  74.         }
  75. }
  76.  
  77.  
  78.  
  79.  
  80.  
  81.  
  82. //class DRichView : public DPanel
  83.  
  84.  
  85. extern "C" void richPanelClickProc(Nlm_PaneL item, Nlm_PoinT mouse)
  86. {
  87.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)item);
  88.     if (obj) obj->Click(mouse);
  89. }
  90.  
  91. extern "C" void richPanelDragProc(Nlm_PaneL item, Nlm_PoinT mouse)
  92. {
  93.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)item);
  94.     if (obj) obj->Drag(mouse);
  95. }
  96.  
  97. extern "C" void richPanelHoldProc(Nlm_PaneL item, Nlm_PoinT mouse)
  98. {
  99.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)item);
  100.     if (obj) obj->Hold(mouse);
  101. }
  102.  
  103. extern "C" void richPanelReleaseProc(Nlm_PaneL item, Nlm_PoinT mouse)
  104. {
  105.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)item);
  106.     if (obj) obj->Release(mouse);
  107. }
  108.  
  109. extern "C" void richPanelDrawProc(Nlm_PaneL item)
  110. {
  111.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)item);
  112.     if (obj) obj->Draw();
  113. }
  114.  
  115. extern "C" void richPanelScrollProc(Nlm_BaR sb, Nlm_SlatE slate, short newval, short oldval)
  116. {
  117.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)slate);
  118.     if (obj) obj->ScrollDoc(sb, newval, oldval);
  119.     //if (obj) obj->Scroll(true, obj, newval, oldval);
  120. }
  121.  
  122. extern "C" void richPanelResetProc(Nlm_PaneL item)
  123. {
  124.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)item);
  125.         // damn, this is called by Vibrant cleaner-upper AFTER DRichView::~DRichView() !!
  126.     if (obj) obj->ResetDoc();
  127. }
  128.  
  129.  
  130. //typedef    short (*CompareFunc)( void*, void*);     // compare two list/array Items 
  131.  
  132. short richPanelCompareStyles( void* item1, void* item2)
  133. {
  134. #if 0
  135.     if ( ((DRichStyle*) item1)->IsNotEqual( (DRichStyle*) item2) ) { 
  136.         if (item1 > item2) return 1;
  137.         else return -1;
  138.         }
  139.     else 
  140.         return 0;
  141. #else
  142.     return MemCmp( item1, item2, sizeof(DRichStyle));
  143. #endif
  144.  
  145.  
  146.  
  147. DRichView::DRichView(long id, DView* itsSuperior, short pixwidth, short pixheight,
  148.             Boolean hasVscroll):
  149.     DPanel(id, itsSuperior, pixwidth, pixheight, DPanel::subclasscreates)
  150. {
  151.      Nlm_SltScrlProc scrollproc;
  152.      fNumItems= 0;
  153.     fNumLines= 0;
  154.     fBarmax= 0;
  155.     fDocFormat= 0;
  156.     fTabCount= 1;
  157.   fAutoAdjust= true; 
  158.   fIsVirtual= false; 
  159.   fDodraw= true;
  160.     fStyles= NULL; 
  161.     fParags= NULL; 
  162.     fCurrentStyle= NULL;
  163.     fSelParag= fSelChar= fSelEndParag= fSelEndChar= 0;
  164.     fSelected= fSelInPict= false;
  165.     ZeroCharWidths();
  166.  
  167. #if 0    
  168.     if (!Nlm_EmptyRect( &DRichTextDoc::gRichDocRect)) {
  169.         pixwidth= DRichTextDoc::gRichDocRect.right - DRichTextDoc::gRichDocRect.left;
  170.         pixheight= DRichTextDoc::gRichDocRect.bottom - DRichTextDoc::gRichDocRect.top;
  171.         }
  172. #endif        
  173.     if (pixwidth ==0) pixwidth = Nlm_screenRect.right - Nlm_screenRect.left - 60;
  174.     if (pixheight==0) pixheight= Nlm_screenRect.bottom - Nlm_screenRect.top - 120;
  175.             // these -## adjustments are not very good -- need to know what other
  176.             // views are in the given window and adjust for their size !?
  177.  
  178.     if (!itsSuperior) return; 
  179.     Nlm_GrouP prnt= (Nlm_GrouP)itsSuperior->GetNlmObject();
  180.     if (!prnt) return; 
  181.   Nlm_WindoW tempPort = Nlm_SavePort(prnt);
  182.   if (hasVscroll) scrollproc= richPanelScrollProc;
  183.   else scrollproc= NULL;
  184.   fPanel= Nlm_AutonomousPanel(prnt, pixwidth, pixheight, richPanelDrawProc,
  185.                                scrollproc, NULL, 0,
  186.                                NULL/*richPanelResetProc*/, NULL);
  187.   if (!fPanel) return; 
  188.   if (tempPort) Nlm_RestorePort(tempPort);
  189.   
  190.     Nlm_SetPanelClick(fPanel, richPanelClickProc, richPanelDragProc, richPanelHoldProc, 
  191.                                         richPanelReleaseProc);
  192.     this->SetNlmObject(fPanel);
  193.     this->SetAutoAdjust(true); // used after append/insert/replace/delete
  194.     this->SetSlateBorder(true);
  195.         
  196.     fStyles= new DList( ::richPanelCompareStyles ); //, DList::kDeleteObjects; // + DList::kOwnObjects 
  197.     fParags= new DList( ); // NULL, DList::kDeleteObjects;
  198.     //fStyles->fArrayIncrement= 30;
  199.     //fParags->fArrayIncrement= 30;
  200.     
  201.     if (gNotInitted) InitRichView();
  202.     fCurrentStyle= new DRichStyle();
  203.     ClearCurrentStyle();
  204.  
  205.     Nlm_LoadRect( &fDrawr, 0,0,0,0);
  206.     fAtpt.x= fAtpt.y= 0;
  207.             
  208.     DWindow* win= this->GetWindow();
  209.     if (win) {
  210.         win->fPrintHandler= this;
  211.         win->fSaveHandler= this;
  212.         }
  213. }
  214.     
  215.  
  216.  
  217.  
  218. DRichView::~DRichView()
  219. {
  220.     //?? need for SetDocData's DocFreeProc call...
  221.     //if (fStyles) delete fStyles; fStyles= NULL;
  222.     //if (fParags) delete fParags; fParags= NULL;
  223.         // damn, delete fList isn't calling object destructors !!!!
  224.     long i, n;
  225.     if (fStyles) {
  226.         n= fStyles->GetSize();
  227.         for (i=0; i<n; i++) {
  228.             DRichStyle* st= (DRichStyle*) fStyles->At(i);
  229.             if (st) delete st;
  230.             }
  231.         delete fStyles;
  232.         }
  233.     if (fParags) {
  234.         n= fParags->GetSize();
  235.         for (i=0; i<n; i++) {
  236.             DParagraph* pa= (DParagraph*) fParags->At(i);
  237.             if (pa) delete pa;
  238.             }
  239.         delete fParags;
  240.         }
  241.     if (fCurrentStyle) {
  242.         fCurrentStyle->ownpict= false;
  243.         delete fCurrentStyle;
  244.         }
  245. }
  246.  
  247. void  DRichView::DeleteAll() 
  248. {
  249.     short i, n;
  250.     if (fStyles) {
  251.         n= fStyles->GetSize();
  252.         for (i=0; i<n; i++) {
  253.             DRichStyle* st= (DRichStyle*) fStyles->At(i);
  254.             delete st;
  255.             }
  256.         fStyles->DeleteAll();
  257.         //delete fStyles;
  258.         }
  259.     if (fParags) {
  260.         n= fParags->GetSize();
  261.         for (i=0; i<n; i++) {
  262.             DParagraph* pa= (DParagraph*) fParags->At(i);
  263.             delete pa;
  264.             }
  265.         fParags->DeleteAll();
  266.         //delete fParags;
  267.         }
  268.     fNumItems= fNumLines= 0;
  269. }
  270.  
  271.  
  272.  
  273. void DRichView::InitRichView()
  274. {
  275.     gNotInitted= true;
  276.   for (short i = 0; i < MAXFONTS; i++) {
  277.     gFontHeights[i].font = NULL;
  278.     gFontHeights[i].height = 0;
  279.       }
  280.     gDrawPict = new DDrawPict();
  281. }
  282.  
  283.  
  284.  
  285. void DRichView::ViewRect( Nlm_RecT& r)  
  286.     DPanel::ViewRect( r);
  287.     Nlm_InsetRect(&r, 10, 4); 
  288. }
  289.  
  290.  
  291.  
  292.     
  293. void DRichView::SetSlateBorder(Boolean turnon) 
  294. {
  295.      Nlm_SetSlateBorder((Nlm_SlatE)fPanel, turnon);  
  296. }
  297.  
  298. void DRichView::SizeToSuperview( DView* super, Boolean horiz, Boolean vert)
  299. {
  300. #if 0
  301. #ifdef WIN_MOTIF
  302.     DPanel::SizeToSuperview( super, horiz, vert);
  303. #else
  304.     // size only lower and right sides == leave top area...
  305.     Nlm_RecT r, myr;
  306.     super->ViewRect(r);
  307.     GetPosition( myr); // ViewRect(myr); <<!!NO, diff from Get/SetPos
  308.     if (horiz)     myr.right= (r.right - r.left) +1;
  309.     // myr.right -= (Nlm_vScrollBarWidth - 8); // mswin patch !?
  310.     if (vert) myr.bottom =  (r.bottom - r.top)  +1; 
  311.     SetPosition( myr);
  312. #endif
  313. #endif
  314. }
  315.   
  316.  
  317. void DRichView::Resize(DView* superview, Nlm_PoinT sizechange)
  318. {
  319.     DPanel::Resize( superview, sizechange);
  320. }
  321.  
  322.  
  323.  
  324.  
  325.  
  326. DRichStyle* DRichView::GetStyle( short styleid)
  327. {
  328.     return (DRichStyle*) fStyles->At(styleid);
  329. }
  330.  
  331. DRichStyle* DRichView::GetStyleAtIndex(DParagraph* aParag, short styleindex)
  332. {    
  333.     short id= -1;
  334.     if (aParag) {
  335.         id= aParag->fStyleIndex[styleindex].styleid;
  336.         return (DRichStyle*) fStyles->At(id);  // id-1?? NO
  337.         }
  338.   else return NULL;
  339. }
  340.  
  341. DRichStyle* DRichView::GetStyleAtChar( DParagraph* aParag, short atchar)
  342. {
  343.     short id= -1;
  344.     if (aParag) {
  345.         short i;
  346.         for (i= aParag->fNumStyles-1; i>0; i--) { 
  347.             if (atchar >= aParag->fStyleIndex[i].nextofs) 
  348.                 break;
  349.             }
  350.         id= aParag->fStyleIndex[i].styleid; 
  351.         }
  352.     return (DRichStyle*) fStyles->At(id);  // id-1?? NO
  353. }
  354.  
  355. DRichStyle* DRichView::GetStyleAtChar( short atparag, short atchar)
  356. {
  357.     return GetStyleAtChar( (DParagraph*)fParags->At(atparag), atchar);
  358. }
  359.  
  360. short DRichView::FindOrAddStyle( DRichStyle* theStyle)
  361.     short styleid= fStyles->GetEqualItemNo( theStyle);
  362.     if (styleid == kEmptyIndex) {
  363.         DRichStyle* bst= new DRichStyle();
  364.         *bst= *theStyle;   // need a smart assign/copy method !! ?? a FIXED clone() ??
  365.         bst->ownpict= true;
  366.         theStyle->fObject= NULL; //theStyle->picdata= NULL;
  367.         fStyles->InsertLast(bst);
  368.         styleid= fStyles->GetSize() - 1;
  369.         }
  370.     return styleid;
  371. }
  372.  
  373.  
  374. DParagraph* DRichView::GetParaPtr( short item)
  375.     return (DParagraph*) fParags->At(item); 
  376. }
  377.  
  378.  
  379.  
  380. DParagraph* DRichView::MakeNewParag( void* data, short lines, 
  381.                         DParagraph* parFormat, DRichStyle* styles, short nstyles, Boolean docOwnsData)
  382. {
  383.     short ist, nst=0;
  384.     //if (styles) do nst++; while (!styles[nst-1].last);
  385.     StyleIndex* styleindex= (StyleIndex*) MemNew( nstyles*sizeof(StyleIndex));
  386.     for (ist=0; ist<nstyles; ist++) {
  387.         short id= FindOrAddStyle( &styles[ist]);
  388.         styleindex[ist].styleid= id;
  389.         styleindex[ist].nextofs= styles[ist].nextofs;
  390.         }
  391.     
  392.     return  new DParagraph( (char*)data, docOwnsData, lines, parFormat, styleindex, nstyles);
  393. }
  394.  
  395.  
  396. void     DRichView::AppendParag( DParagraph* aParag)
  397. {    
  398.   if (aParag) {
  399.         aParag->startsAt= fNumLines;
  400.     fNumLines += aParag->numRows;
  401.         fParags->InsertLast(aParag);
  402.     fNumItems++; // == fParags->GetSize();
  403.       }
  404. }
  405.  
  406. void     DRichView::Append( void* data, short lines, DParagraph* parFormat,  
  407.                         DRichStyle* styles, short nstyles, Boolean docOwnsData)
  408. {    
  409.     DParagraph* aParag= MakeNewParag( data, lines, parFormat, styles, nstyles, docOwnsData);
  410.   if (aParag) {
  411.     UpdateItemHeights(aParag);
  412.     AppendParag( aParag);
  413.     if (fAutoAdjust) AdjustScroll();
  414.       }
  415. }
  416.  
  417. void     DRichView::Insert( short item, void* data, short lines, DParagraph* parFormat, 
  418.                         DRichStyle* styles, short nstyles, Boolean docOwnsData)
  419. {
  420.     DParagraph* aParag= MakeNewParag( data, lines, parFormat, styles, nstyles, docOwnsData);
  421.   if (aParag) {
  422.     UpdateItemHeights(aParag);
  423.         DParagraph* pat= (DParagraph*)fParags->At(item);
  424.         if (pat) {
  425.             aParag->startsAt= pat->startsAt;
  426.             fParags->InsertBefore(item, aParag);
  427.         fNumLines = UpdateLineStarts(item);
  428.             fNumItems++; // == fParags->GetSize();
  429.         }
  430.       else {
  431.             AppendParag( aParag);    
  432.           }
  433.     if (fAutoAdjust) AdjustScroll();
  434.       }
  435. }
  436.  
  437. void     DRichView::Replace( short item, void* data, short lines, DParagraph* parFormat,  
  438.                 DRichStyle* styles, short nstyles, Boolean docOwnsData)
  439. {
  440.     DParagraph* aParag= MakeNewParag( data, lines, parFormat, styles, nstyles, docOwnsData);
  441.   if (aParag) {
  442.     UpdateItemHeights(aParag);
  443.         DParagraph* pat= (DParagraph*) fParags->At(item);
  444.         if (pat) {
  445.             aParag->startsAt= pat->startsAt;
  446.             fParags->AtPut(item, aParag);
  447.         fNumLines = UpdateLineStarts(item);
  448.             delete pat; // !? should DList do this on AtPut ?? it doesn't
  449.         }
  450.       else {
  451.             AppendParag( aParag);
  452.           }
  453.     if (fAutoAdjust) AdjustScroll();
  454.       }
  455. }
  456.  
  457.  
  458. void     DRichView::UpdateStyleHeight( DRichStyle* theStyle)
  459. {
  460.   if (theStyle) {
  461.       short theid= fStyles->GetIdentityItemNo( theStyle);
  462.         if (theid == kEmptyIndex) return;
  463.         
  464.       short j, item, nitem= fParags->GetSize();
  465.       for (item= 0; item<nitem; item++) {
  466.             DParagraph* pat= (DParagraph*) fParags->At(item);
  467.             for (j= 0; j< pat->fNumStyles; j++) {
  468.                 if (pat->fStyleIndex[j].styleid == theid) {
  469.                 short rtop, rbottom, firstline;
  470.                 UpdateItemHeights(pat);
  471.                 if (IsVisible( item, rtop, rbottom, firstline )) {
  472.                     Nlm_RecT    rec;
  473.                     ViewRect( rec);
  474.                         rec.top= rtop;
  475.                         InvalRect( rec);
  476.                     }
  477.                 break;
  478.                 }
  479.             }
  480.         }
  481.     if (fAutoAdjust) AdjustScroll();
  482.       }
  483. }
  484.  
  485.  
  486.  
  487.  
  488.  
  489. short DRichView::GetItemNum(short desiredLine)
  490. {
  491.     // Returns the number of the paragraph containing the desired line
  492.  
  493.   short mid = 1;
  494.   short left = 1;
  495.   short right = fNumItems;
  496.   Boolean goOn = TRUE;
  497.   while (left <= right && goOn) {
  498.     mid = (left + right) / 2;
  499.     DParagraph* aParag = GetParaPtr(mid - 1);
  500.     if (aParag) {
  501.       if (desiredLine < aParag->startsAt + aParag->numRows)  
  502.         right = mid - 1;
  503.       if (desiredLine >= aParag->startsAt)  
  504.         left = mid + 1;
  505.         } 
  506.     else {
  507.       goOn = FALSE;
  508.       mid = 1;
  509.         }
  510.   }
  511.   return mid - 1;
  512. }
  513.  
  514.  
  515.  
  516. void DRichView::SetStyle(DRichStyle* theStyle)
  517. {
  518.     if (!theStyle || theStyle->linkid || theStyle->ispict) 
  519.         return; /* do these styles separately */
  520.     if (theStyle->font != fCurrentStyle->font) 
  521.         Nlm_SelectFont(theStyle->font);
  522.     if (theStyle->color != fCurrentStyle->color)
  523.         Nlm_SetColor(theStyle->color);
  524.  
  525.     ZeroCharWidths();
  526.     *fCurrentStyle = *theStyle;
  527. }
  528.  
  529.  
  530. void DRichView::ClearCurrentStyle()
  531. {
  532.     fCurrentStyle->ispict= false;
  533.     fCurrentStyle->ismap= false;
  534.     fCurrentStyle->ownpict= false;
  535.     fCurrentStyle->fObject= NULL; //fCurrentStyle->picdata= NULL;
  536.     fCurrentStyle->font= NULL;
  537.     fCurrentStyle->superSub= 0;
  538.     fCurrentStyle->color= 0;
  539. }
  540.  
  541.  
  542.  
  543. short DRichView::CharWidth(char ch)
  544. {
  545.     unsigned char cw= fCharWidths[ch];
  546.     if (cw == kNoCharWidth) {
  547.         cw= Nlm_CharWidth(ch);
  548.          fCharWidths[ch]= cw;
  549.          }
  550.     return cw;
  551. }
  552.  
  553. void DRichView::ZeroCharWidths()
  554. {
  555.     Nlm_MemFill( fCharWidths, kNoCharWidth, 256); // sizeof(fCharWidths)
  556. }
  557.  
  558. short DRichView::StyleLineWidth(char* texts, short maxwid, DParagraph* itemPtr, short& istyle)
  559. {
  560.   Char               ch;
  561.   short              i,swid,wid,nextofs,numStyles;
  562.     Boolean         styleset;
  563.     DRichStyle * atstyle, savestyle;
  564.     
  565.   styleset= FALSE;
  566.   i = wid = swid = 0;
  567.     nextofs= itemPtr->fStyleIndex[istyle].nextofs;
  568.     numStyles= itemPtr->fNumStyles;
  569.     atstyle= GetStyleAtIndex(itemPtr, istyle);
  570.     savestyle= *atstyle;
  571.     
  572.      if (atstyle->ispict) wid += atstyle->pixwidth; 
  573.     if (texts && maxwid > 0) {
  574.     ch = texts[i];
  575.     while (ch != '\0' && ch != '\n' && ch != '\r' && wid <= maxwid) {
  576.  
  577.       if (i>=nextofs && istyle<numStyles-1) {  // && !atstyle->last    
  578.                 ++istyle;
  579.                 nextofs= itemPtr->fStyleIndex[istyle].nextofs;
  580.                 atstyle= GetStyleAtIndex(itemPtr, istyle);
  581.              SetStyle(atstyle);
  582.              styleset= TRUE;
  583.               if (atstyle->ispict) wid += atstyle->pixwidth; 
  584.         }
  585.         
  586.       else if (!atstyle->hidden) {
  587.             if (ch == '\t') {
  588.                         // fix this tab width !!!
  589.                   }
  590.             else wid += CharWidth(ch);
  591.           }
  592.       
  593.       i++;
  594.       ch = texts [i];
  595.         }
  596.       }
  597.     if (styleset) SetStyle( &savestyle);
  598.     savestyle.ownpict= false;
  599.   return wid;
  600. }
  601.  
  602.  
  603.  
  604. short DRichView::FitTextToWidth(char* texts, short maxwid, Boolean byPixels,
  605.                           DParagraph* itemPtr, short& istyle)
  606. {
  607.             // Returns the number of characters in the next block, including 
  608.             // trailing spaces (which are trimmed back later)
  609.   Char  ch;
  610.   short  i,j,wid, swid, nextofs, numStyles;
  611.     Boolean wordWrap, styleset;
  612.     DRichStyle *atstyle, savestyle;
  613.     
  614.     nextofs= itemPtr->fStyleIndex[istyle].nextofs;
  615.     numStyles= itemPtr->fNumStyles;
  616.     atstyle= GetStyleAtIndex(itemPtr, istyle);
  617.     SetStyle(atstyle); // be sure ??
  618.     savestyle= *atstyle;
  619.     wordWrap= itemPtr->wrap;
  620.   i = j = 0;
  621.   wid = swid = 0;
  622.   if (texts && maxwid > 0) {
  623.     ch = texts [i];
  624.     while (ch != '\0' && ch != '\n' && ch != '\r' && wid <= maxwid) {
  625.       if (wordWrap) {
  626.           if (i>=nextofs && istyle<numStyles-1) {   //if (ch == chStyleTag) 
  627.                     ++istyle;
  628.                     nextofs= itemPtr->fStyleIndex[istyle].nextofs;
  629.                     atstyle= GetStyleAtIndex(itemPtr, istyle);
  630.                SetStyle(atstyle);
  631.                styleset= TRUE;
  632.                 if (atstyle->ispict && byPixels) wid += atstyle->pixwidth; 
  633.             }
  634.             
  635.         else if (!atstyle->hidden) {
  636.               if (ch == '\t') {
  637.                         /* !!! FIX THIS !?!?! */
  638.                 }
  639.           else if (byPixels) wid += CharWidth (ch);
  640.           else wid++;
  641.             }
  642.           }
  643.       i++;
  644.       ch = texts [i];
  645.         }
  646.           
  647.     j = i;
  648.     if (wordWrap && wid > maxwid) {
  649.         // don't break in a word, and leave trailing spaces at end of line 
  650.       j--;
  651.       if (byPixels)  
  652.         while (Nlm_TextWidth(texts, i) >= maxwid)  i--;
  653.       else 
  654.         while (i >= maxwid) i--;
  655.       while (i > 0 && texts[i - 1] != ' ' && texts[i - 1] != '-')  i--;
  656.       while (texts [i] == ' ')  i++;
  657.         }
  658.         
  659.       }
  660.     if (styleset) SetStyle( &savestyle);
  661.     savestyle.ownpict= false; //!!
  662.   if (i > 0 && i < j) return i;
  663.     else if (j > 0) return j;
  664.     else  return 0;
  665. }
  666.  
  667.  
  668.  
  669.  
  670.  
  671.  
  672. void DRichView::ParseText(DParagraph* itemPtr, char* text, Boolean byPixels, Nlm_RecT r)
  673. {
  674.             //  Parses text that contains \t, \r and \n characters into a list of
  675.             //  cells organized by row and column
  676.  
  677.   char        ch, just;
  678.   short       inset,
  679.             istyle, numStyles, col, blklen, len,width,maxwid,
  680.                       numRows,tabRow,returnRow,row;
  681.   Uint2        start;
  682.   Boolean      wrap;
  683.     char          * newtex;
  684.     ulong         maxsize, newsize;
  685.     
  686.   if (itemPtr && text && *text != '\0') {
  687.       numStyles= itemPtr->fNumStyles;
  688.        istyle= 0;
  689.     if (numStyles) {
  690.         DRichStyle savestyle;
  691.         savestyle= *fCurrentStyle;
  692.         ClearCurrentStyle();
  693.         SetStyle(GetStyleAtIndex(itemPtr, istyle));
  694.         
  695.         if (*text == '\n' && text[1] == '\0') {
  696.             // ?? Win32 bug - failing w/ multiple '\n's ??!!
  697.             newtex = (char*) MemNew (5 + itemPtr->minLines);
  698.                newtex[0]= '\n';
  699.               newtex[1]= '\0';
  700.         itemPtr->numRows = MAX (1, itemPtr->minLines);
  701.               itemPtr->fText = newtex;
  702.               SetStyle(&savestyle);
  703.               savestyle.ownpict= false; // !!
  704.               return;
  705.               }
  706.               
  707.           maxsize= (ulong) (StrLen(text) + 50 + itemPtr->minLines);
  708.           newsize= 0;
  709.           newtex = (char*) MemNew (maxsize);
  710.          
  711.       width = 0;
  712.       inset = itemPtr->leftInset; /* pixLeft, pixFirst ?? */
  713.       just = itemPtr->just; /*'l';*/
  714.       wrap = itemPtr->wrap; /* TRUE; /* fix this as choice ... */
  715.       start = 0;
  716.       row = 0;
  717.       tabRow = 0;
  718.       returnRow = 1;
  719.       col = 0;
  720.       numRows = 0;
  721.       while (text[start] != '\0') {
  722.         ch = text[start];
  723.         if (ch != '\0' && ch != '\n' && ch != '\r'  ) {
  724.           maxwid =  r.right - r.left - 15; // !!! Need PAGEWIDTH here !!
  725.           short istyle0= istyle;                    
  726.           blklen =  FitTextToWidth(text + start, maxwid, byPixels, 
  727.                               itemPtr, istyle);
  728.                 if (istyle!=istyle0) SetStyle(GetStyleAtIndex(itemPtr, istyle));
  729.           len = blklen;
  730.           
  731.           if (len > 0) {
  732.             if (text[start + len] != '\0') { // eat trailing spaces 
  733.               while (len > 0 && text [start + len - 1] == ' ') len--;
  734.               if (len == 0) len = blklen;
  735.                 }
  736.             if (newsize+len > maxsize) {
  737.                 maxsize= newsize+len+100;
  738.                 newtex= (char*) MemMore(newtex, maxsize);  
  739.                 }
  740.             MemCpy( newtex+newsize, text+start, len);
  741.             newsize += len;
  742.             start += blklen;
  743.               } 
  744.               
  745.           else { // len==0, shouldn't be true ? 
  746.  
  747.               }
  748.             }
  749.             
  750.         ch = text [start];
  751.         if (ch == '\n') {
  752.                  newtex[newsize++]= '\n';
  753.               start++;
  754.           row = returnRow;
  755.           tabRow = row;
  756.           returnRow++;
  757.           col = 0;
  758.             } 
  759.         else if (ch == '\r') {
  760.                  newtex[newsize++]= '\n';
  761.           start++;
  762.           row++;
  763.           returnRow = MAX (returnRow, row + 1);
  764.                } 
  765. #if 0
  766.         else if (ch == '\t') {
  767.           start++;
  768.           row = tabRow;
  769.               newtex[newsize++]= '\t';
  770.           if (text [start] == '\0') row = returnRow;
  771.             } 
  772. #endif
  773.         else if (ch != '\0' && wrap) {
  774.               newtex[newsize++]= '\n';
  775.           if (len == 0) start++;
  776.           row++;
  777.           returnRow = MAX (returnRow, row + 1);
  778.             } 
  779.         else if (ch != '\0') 
  780.             start++;
  781.         else if (text [start - 1] != '\n' && text [start - 1] != '\r')  
  782.           row = returnRow;
  783.          
  784.         numRows = MAX (numRows, row);
  785.           }
  786.       itemPtr->numRows = MAX (numRows, itemPtr->minLines);
  787.             newtex[newsize++]= '\0';
  788.             itemPtr->fText = newtex;
  789.             SetStyle(&savestyle);
  790.             savestyle.ownpict= false; // !!
  791.         }
  792.       } 
  793.   else if (itemPtr != NULL)  
  794.     itemPtr->numRows = 0;
  795. }
  796.  
  797.  
  798.  
  799.  
  800.  
  801. // temp globals...
  802.  
  803. static short gMapOfs = 0;
  804. //static DRichStyle* gMapStyle = NULL;
  805.  
  806. short DRichView::DrawStyledItem(DParagraph* itemPtr, Nlm_RectPtr rpara, short item,
  807.                                       short frst, Boolean forPrinter, Nlm_PoinT* mapPoint)
  808. {
  809.                 // Draws a given paragraph(item) on the screen, using parag & char styles 
  810.   char         ch, just, csave;
  811.   Boolean      isnewline, bartab, dotab, mapPt, drawSelection, gray, doborder;
  812.   char         * ptext, * text;
  813.   unsigned long            nextofs;
  814.   short     lineHeight, num, row, rsult, rleft, rright, rbottom, width, maxwid,
  815.                          istyle,styleid, istyle2, numStyles, superSub, txtwidth, yfont; 
  816.                       
  817.   DRichStyle    * astyle;  
  818.   Nlm_RecT         rct; // drw
  819.     Nlm_PoinT            pt1, pt2; //, atpt;
  820.     
  821.     mapPt= (mapPoint != NULL);
  822.     if (mapPt) fMapStyle= NULL;
  823.     fDodraw= (mapPoint == NULL);
  824.     drawSelection= (fSelected && fDodraw && !forPrinter 
  825.                                     && item >= fSelParag && item <= fSelEndParag);
  826.   rsult = 0;
  827.   if (itemPtr && rpara) {
  828.     text = itemPtr->fText;
  829.     numStyles= itemPtr->fNumStyles;
  830.     
  831.     if (text && *text != '\0') {
  832.         just= itemPtr->just;
  833.       lineHeight = itemPtr->lineHeight;
  834.       rct.top = rpara->top;
  835.       rct.bottom = rct.top;
  836.             rbottom = rct.top + lineHeight * (itemPtr->numRows - frst);
  837.              rleft= fAtpt.x = rpara->left + itemPtr->leftInset + itemPtr->firstInset;
  838.       fAtpt.y = rpara->top;
  839.       row = 0;
  840.       txtwidth= 0;
  841.       ptext = text;
  842.       ch = *ptext;
  843.           gray = FALSE;
  844.             isnewline= TRUE;
  845.  
  846. //Debug("1");
  847.          istyle= 0;
  848.          styleid= itemPtr->fStyleIndex[istyle].styleid;
  849.          nextofs= itemPtr->fStyleIndex[istyle].nextofs;
  850.              astyle= GetStyle(styleid);
  851.  
  852.             Nlm_LoadRect(&fDrawr, rleft, rpara->top, rpara->right, rbottom);
  853.             
  854.       if (itemPtr->newPage) {
  855.           /* probably on line by self... */
  856.           /* record footnote text somewhere and dump out here before page break... */
  857.           if (fDodraw && !forPrinter) {
  858.                     Nlm_Dashed(); // Nlm_Dotted(); 
  859.                 Nlm_FrameRect(&fDrawr);
  860.                     Nlm_ResetDrawingTools();
  861.                     }
  862.           }
  863.                        
  864.          ClearCurrentStyle();
  865.          SetStyle(astyle);
  866.             superSub= astyle->superSub;
  867.             
  868.       while (ch != '\0') {
  869.       
  870.         if (ch == '\n') {
  871.           rct.top = rpara->top + (row - frst) * lineHeight;
  872.           rct.bottom = rct.top + lineHeight;
  873.             rleft= fAtpt.x = rpara->left + itemPtr->leftInset;
  874.           row++;
  875.           ptext++; 
  876.           isnewline= TRUE;
  877. //Debug("/");
  878.             } 
  879.                     
  880.         else if (ch == chPictTag) {
  881.           ptext++;
  882.             } 
  883.            
  884.         else  {
  885.         
  886.                     while ( (ptext - text >= nextofs) && (istyle < numStyles-1)) {
  887. //Debug("s");
  888.                      istyle++;
  889.                      styleid= itemPtr->fStyleIndex[istyle].styleid;
  890.                      nextofs= itemPtr->fStyleIndex[istyle].nextofs;
  891.                      if (!((ptext - text >= nextofs) && (istyle < numStyles-1))) {
  892.                              astyle= GetStyle(styleid);
  893.                          SetStyle(astyle);
  894.                             superSub= astyle->superSub;
  895.                             }
  896.                         }
  897.  
  898.                   if (isnewline) {
  899.                          doborder= itemPtr->DoBorder();
  900.  
  901.                 if (just != 'l') {
  902.                     istyle2= istyle;
  903.                   maxwid=  rpara->right - rpara->left; //!!! Need PAGEWIDTH here !!
  904.                              width= StyleLineWidth( ptext, maxwid, itemPtr, istyle2);
  905.                              if (width<maxwid) {
  906.                                  switch (just) {
  907.                                      case 'r': 
  908.                                          fAtpt.x= /*rleft= */ MAX( rleft, rpara->right - itemPtr->rightInset - width); 
  909.                                          break;
  910.                                      case 'c': { 
  911.                                          short rhalf= ((rpara->right - itemPtr->rightInset - rleft) - width) / 2; 
  912.                                          if (rhalf>0) fAtpt.x= rleft += rhalf;
  913.                                          }
  914.                                          break;
  915.                                      }
  916.                                  }
  917.                     }
  918.                       isnewline= FALSE;
  919.                       }
  920.                       
  921.                 num = 0;
  922.                 while ( ch == '\t') ch= ptext[++num];
  923.           while ( ch != '\0' && ch != '\n' && ch != '\t' 
  924.               && ( (num + ptext - text) < nextofs))   
  925.                 ch = ptext[++num];
  926.  
  927.           if (row >= frst) {
  928.                     Boolean inrect;
  929.  
  930.  //Debug("r");
  931.             rct.top = rpara->top + (row - frst) * lineHeight;
  932.             rct.bottom = rct.top + lineHeight;
  933.             rct.left = fAtpt.x;  
  934.             rct.right = rpara->right - itemPtr->rightInset; 
  935.                         if (doborder && row == itemPtr->numRows-1 
  936.                             && (itemPtr->borderbottom || itemPtr->borderbox)) 
  937.                                 rct.bottom--;
  938.             Nlm_LoadRect (&fDrawr, MAX (rct.left, rpara->left), rct.top,
  939.                       MIN (rct.right, rpara->right), rct.bottom);
  940.  
  941. #if 1
  942.                         inrect= (rct.top <= rpara->bottom && rct.bottom > rpara->top);
  943. #else
  944.                          inrect= Nlm_SectRect( &fDrawr, rpara, &rsect);
  945. #endif
  946.             if ( inrect && (mapPt || forPrinter || Nlm_updateRgn == NULL ||
  947.                      Nlm_RectInRgn (&rct, Nlm_updateRgn))) {
  948.               fDrawr = rct;
  949.                             fDrawr.top += superSub; 
  950.                             fDrawr.bottom += superSub;  
  951. // Debug1("%d",num);
  952.               if (num > 0  && !(astyle->hidden)) {
  953. // Debug("i");
  954.                   just= 'l';
  955.                        bartab= FALSE;
  956.                      dotab= FALSE;
  957.  
  958.                         /* yfont= fDrawr.top + Nlm_Ascent();  /* a. large font mismatch */
  959.                            /* yfont= fDrawr.bottom - Nlm_Descent() - Nlm_Leading(); /* b. better than a */
  960.                            /* yfont= fDrawr.bottom - Nlm_Descent(); /* c. almost perfect, slight font mismatch */
  961.                         /* yfont= fDrawr.top + Nlm_FontHeight(); /* d. bad, too low, font mismatch */
  962.                            yfont= fDrawr.bottom - 4; /* Nlm_stdDescent; /* e. !! YES, but what is right ## ?? */
  963.                            /* yfont= fDrawr.top + Nlm_FontHeight() - Nlm_Descent(); /* f. ?? */
  964.  
  965.                 while (num > 0 && *ptext == '\t') {
  966.                   dotab= TRUE;
  967.                   num--;
  968.                   ptext++;
  969.                                     itemPtr->SetTab( *ptext == '\t', rleft, fDrawr, rpara, bartab, just);
  970.                     fAtpt.x = fDrawr.left; /* ??? */
  971.                     }
  972.                     
  973.                             if (dotab) 
  974.                                 itemPtr->DrawTab( this, rct, fDrawr, fAtpt, yfont, bartab, fDodraw);
  975.  
  976.                     if (astyle->allcaps || astyle->smallcaps) { 
  977.                         char* cp= ptext;
  978.                         for (short i=0; i<num; i++) cp[i]= to_upper(cp[i]);
  979.                             // need to shift fontsize down for lowercases 
  980.                         }
  981.  
  982.                         txtwidth= Nlm_TextWidth(ptext, num); 
  983.                          
  984.                   switch (just) {
  985.                          case 'c': 
  986.                              rright= (fDrawr.left + txtwidth + fDrawr.right)/ 2; 
  987.                                         fDrawr.left += (fDrawr.right - fDrawr.left - txtwidth) / 2; 
  988.                              break;
  989.                          case 'r':
  990.                              rright = fDrawr.right; 
  991.                              fDrawr.left = fDrawr.right - txtwidth; 
  992.                              break;
  993.                          default:
  994.                          case 'l':
  995.                                    /* rright= fDrawr.left + astyle->pixwidth; */
  996.                                 rright= fDrawr.left + txtwidth + 1;
  997.                              break;
  998.                          }
  999.                          
  1000.                      /* these are no good for multilines w/ same style, & resizing changes */
  1001.                                 if (astyle->pixwidth==0) astyle->pixwidth= rright - fAtpt.x;
  1002.                                 astyle->pixleft= fAtpt.x;
  1003.  
  1004. #if 0
  1005.     // this looks too messy !!
  1006.     // ?? quick fix for html text that is off screen to left or right ?
  1007.                                 if (rright > rpara->right) Nlm_OffsetRect( &fDrawr, rpara->right-rright, 0);
  1008.                                 if (fDrawr.left < rpara->left) fDrawr.left= rpara->left;
  1009. #endif
  1010.                                 
  1011.                      Nlm_MoveTo(fDrawr.left, yfont);  // yfont == adjust for leading
  1012.                      if (fDodraw) {
  1013.                          csave= ptext[num]; ptext[num]= 0;
  1014.                          Nlm_PaintString(ptext);
  1015.                      ptext[num]= csave;                                    
  1016.                               }
  1017.  
  1018.                      else if (mapPoint && Nlm_PtInRect( *mapPoint, &fDrawr)) {
  1019.                          if (astyle->ispict) {
  1020. #if 0
  1021.                                         astyle->fObject->FindPt( fDrawr, pt);
  1022.                                         // return isInPict && point-rel to pict && astyle or styleid !!
  1023. #endif
  1024.                                 fAtpt.x= rright;
  1025.                              fDrawr.left= fAtpt.x;  
  1026.                              gMapOfs= (short)(ptext - text); // pict point ??
  1027.                            fMapStyle= astyle;
  1028.                              return gMapOfs; // text point..
  1029.                              }
  1030.                          else {
  1031.                              // return also num chars !?
  1032.                              short atx= mapPoint->x - fDrawr.left;
  1033.                              short    i= num;
  1034.                              if (Nlm_TextWidth(ptext, i) >= atx) {
  1035.                                  while (i>0 && Nlm_TextWidth(ptext, i) > atx) i--;
  1036.                                  gMapOfs= (short)(ptext + i - text);
  1037.                                             fMapStyle= astyle;
  1038.     
  1039.                                      // !! not finding proper style (for links)
  1040.                                  short ist= istyle;
  1041.                                  short nof= nextofs;
  1042.                                  short sid= styleid;
  1043.                                  while ( gMapOfs >= nof && ist < numStyles-1 ) {
  1044.                                              ist++;
  1045.                                              sid= itemPtr->fStyleIndex[ist].styleid;
  1046.                                              nof= itemPtr->fStyleIndex[ist].nextofs;
  1047.                                                 fMapStyle= GetStyle(sid);
  1048.                                                 }
  1049.                                  return gMapOfs; // text point..
  1050.                                  }
  1051.                              else {
  1052.                                  // ??? continue on for more of ptext, if proper line ...
  1053.                                  // there must be some mistake in fDrawr if we get here??
  1054.                                  }
  1055.                              }
  1056.                          }
  1057.  
  1058.                                 if (astyle->linkid && fDodraw) {
  1059.                                   if (!forPrinter) {
  1060.                                          Nlm_SetColor(astyle->color);
  1061. #if 1
  1062.                                         Nlm_WidePen(2);
  1063.                                         /* Nlm_Dotted(); /* Nlm_Dashed(); */
  1064.                                         Nlm_MoveTo( fDrawr.left, fDrawr.bottom-2);
  1065.                                         Nlm_LineTo( rright-1, fDrawr.bottom-2);
  1066.                                         Nlm_WidePen(1);
  1067.                                         Nlm_Solid();
  1068. #else
  1069.                                         fDrawr.right= rright-1;
  1070.                                         Nlm_FrameRect( &fDrawr);
  1071. #endif
  1072.                                         Nlm_SetColor(fCurrentStyle->color);
  1073.                                         }
  1074.                                     }
  1075.                                 else if (astyle->boxed && fDodraw) {
  1076.                                     fDrawr.right= rright-1;
  1077.                                     Nlm_FrameRect( &fDrawr);
  1078.                                     }
  1079.  
  1080.                                 Nlm_Black(); /* need this or something like to fix color bug in XWin */
  1081.  
  1082.                                 if (drawSelection) {
  1083.                                     short textofs= ptext - text; 
  1084.                                     short textend= textofs + num; 
  1085.                                     Nlm_RecT selr= fDrawr;
  1086.                                     Boolean showsel= true;
  1087.                                     short  baseleft= selr.left;
  1088.                                     
  1089.                                     if (item == fSelParag) {
  1090.                                         if (textend < fSelChar) showsel= false;
  1091.                                         if (showsel && textofs < fSelChar) 
  1092.                                             selr.left = MIN( selr.right, 
  1093.                                                 baseleft + Nlm_TextWidth( ptext, fSelChar - textofs));
  1094.                                         }
  1095.                                         
  1096.                                     if (showsel && item == fSelEndParag) {
  1097.                                       if (textofs > fSelEndChar) showsel= false;
  1098.                                         if (showsel && textofs < fSelEndChar) //textend > fSelEndChar
  1099.                                             selr.right = MAX(selr.left, 
  1100.                                                 baseleft + Nlm_TextWidth( ptext, fSelEndChar - textofs));
  1101.                                         }
  1102.  
  1103.                                     if (showsel) Nlm_InvertRect( &selr);
  1104.                                     }
  1105.                                     
  1106.                                     
  1107.                         fAtpt.x= rright;
  1108.  
  1109.                    if (astyle->strikeout && fDodraw) {
  1110.                        short dmid= (fDrawr.top + fDrawr.bottom) / 2;
  1111.                        Nlm_MoveTo( fDrawr.left, dmid);
  1112.                        Nlm_LineTo( fAtpt.x, dmid);
  1113.                        }
  1114.                      fDrawr.left= fAtpt.x;  
  1115.  
  1116.                                 if (astyle->ispict) {
  1117.                                     fDrawr.right = fDrawr.left + astyle->pixwidth;
  1118.                                     fDrawr.bottom= fDrawr.top + astyle->pixheight;
  1119.                                   fAtpt.x= fDrawr.right+1;
  1120.                                     if (fDodraw) {
  1121.                                         if (astyle->fObject) astyle->fObject->Draw( fDrawr);
  1122.                                         Nlm_ResetDrawingTools();
  1123.                                         }
  1124.                                     fDrawr.left= fAtpt.x;
  1125.                                     }
  1126.                    }
  1127.                  fDrawr.right = rct.right;
  1128.               
  1129.                             if (doborder && fDodraw) {
  1130.                                 itemPtr->DrawBorder( this, row, item, rpara, rct);
  1131.                                  doborder= FALSE;
  1132.                                 }
  1133.  
  1134.               }
  1135.               }
  1136.                     if (!num) ptext++; else ptext += num;
  1137.             }
  1138.         ch = *ptext;
  1139.              }
  1140.       rct.top = rct.bottom;
  1141.       rsult = rct.top - rpara->top;
  1142.         }
  1143.     Nlm_SelectFont(Nlm_programFont);  //Nlm_systemFont
  1144.       }
  1145.   if (mapPt) return -1;   // couldn't find mapPoint if we got here
  1146.   else return rsult;
  1147. }
  1148.  
  1149.  
  1150.  
  1151.  
  1152.  
  1153. char* DRichView::DataToChar(char* ptr)  
  1154. {
  1155.   if (ptr) 
  1156.     return Nlm_StringSave((char*)ptr);
  1157.   else 
  1158.     return NULL;
  1159. }
  1160.  
  1161.  
  1162. void DRichView::FormatText( short item, DParagraph* itemPtr, Boolean byPixels)
  1163. {
  1164.         // parses and rearranges the text so that it can be displayed, saved, or printed
  1165.   char           ch;
  1166.   Boolean        needToParse;
  1167.   short       numRows;
  1168.   char*            text;
  1169.     Nlm_RecT        r;
  1170.     
  1171.     /* dgg &fix this */
  1172.  
  1173.   if (itemPtr && itemPtr->fText == NULL) {
  1174.         this->ViewRect( r);
  1175.     needToParse = TRUE;
  1176.         text = this->DataToChar(itemPtr->fDataPtr);
  1177.           
  1178.     if (needToParse && text && *text != '\0') {
  1179.           if (*text == '\n' && text[1] == '\0') {
  1180.           itemPtr->fText = text;
  1181.           itemPtr->numRows = 1;
  1182.                }
  1183.       else {
  1184.           ParseText(itemPtr, text, byPixels, r);
  1185.           MemFree(text);
  1186.           }
  1187.       itemPtr->notCached = FALSE;
  1188.       itemPtr->neverCached = FALSE;
  1189.         } 
  1190.     else  
  1191.       itemPtr->fText = text;
  1192.      
  1193.     text = itemPtr->fText;
  1194.     if (text == NULL || *text == '\0') {
  1195.       MemFree(itemPtr->fText);
  1196.       itemPtr->fText = StringSave(" \n");
  1197.       itemPtr->numRows = 1;
  1198.       itemPtr->notCached = FALSE;
  1199.       itemPtr->neverCached = FALSE;
  1200.         } 
  1201.     else if (fIsVirtual) {
  1202.       numRows = 0;
  1203.       ch = *text;
  1204.       while (ch != '\0') {
  1205.         if (ch == '\n') numRows++;
  1206.         text++;
  1207.         ch = *text;
  1208.           }
  1209.       numRows = MAX (1, numRows);
  1210.       itemPtr->numRows = MAX (numRows, itemPtr->minLines);
  1211.         }
  1212.   }
  1213. }
  1214.  
  1215.  
  1216. short DRichView::GetLineStart(short item)
  1217. {
  1218.             // Returns the first line of the item
  1219.   DParagraph*  itemPtr = GetParaPtr(item);  
  1220.   if (itemPtr) return itemPtr->startsAt;
  1221.   else return 0;
  1222. }
  1223.  
  1224. short DRichView::GetNumRows(short item)
  1225. {
  1226.                 //   Returns the number of rows in the item
  1227.   DParagraph*  itemPtr  = GetParaPtr( item);  
  1228.   if (itemPtr)  return itemPtr->numRows;
  1229.   else return 0;
  1230. }
  1231.  
  1232. short DRichView::GetLineHeight(short item)
  1233. {
  1234.         //     Returns the pixel height of the item
  1235.   DParagraph*  itemPtr  = GetParaPtr( item);  
  1236.   if (itemPtr)  return itemPtr->lineHeight;
  1237.   else return 0;
  1238. }
  1239.  
  1240.  
  1241.  
  1242.  
  1243.     
  1244. Boolean DRichView::Doc2ViewOffset(short& xoff, short& yoff)
  1245. {
  1246.   Nlm_RecT             viewr, rct;
  1247.   short             atline, itemNum, leadHeight, lineHeight, numRows, off;
  1248.   Nlm_BaR          sb;
  1249.   DParagraph*      itemPtr;
  1250.     
  1251.     ViewRect( viewr);
  1252.     Nlm_LoadRect( &rct, 0, 0, viewr.right - viewr.left, 0);
  1253.   sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) fPanel);
  1254.     if (sb) off = Nlm_GetValue(sb); // line offset of view
  1255.     else off= 0;
  1256.     
  1257.     //for (atline=0; atline<= off; atline++)  
  1258.     atline = 0;
  1259.     leadHeight = 0;
  1260.     itemNum = 0; //= GetItemNum( atline);
  1261.     while (itemNum < fNumItems && atline < off) {
  1262.         itemPtr = GetParaPtr( itemNum);
  1263.       if (itemPtr) {
  1264.             rct.top = rct.bottom + leadHeight;
  1265.       CacheIfNever( itemNum + 1, itemPtr, &viewr);
  1266.           if (atline>0) rct.top += itemPtr->spaceBefore;
  1267.       lineHeight = itemPtr->lineHeight;
  1268.       rct.top += leadHeight;
  1269.       numRows = itemPtr->numRows;
  1270.       rct.bottom = rct.top + lineHeight * (numRows) + itemPtr->spaceAfter;
  1271.            leadHeight = itemPtr->leadHeight;
  1272.           atline += numRows;
  1273.             }
  1274.         itemNum++;
  1275.         }
  1276.  
  1277.     xoff = rct.left;
  1278.     yoff = rct.top; // - viewr.top; // ??? was +top
  1279.     return true;
  1280. }    
  1281.  
  1282.     
  1283. Boolean DRichView::MapDoc2View( Nlm_RecT& selr)
  1284. {
  1285.   Nlm_RecT     viewr, rct;
  1286.     short        xoff, yoff;
  1287.  
  1288.     Doc2ViewOffset(xoff, yoff);
  1289.     selr.left         -= xoff;
  1290.     selr.right     -= xoff;
  1291.     selr.top         -= yoff;
  1292.     selr.bottom -= yoff;
  1293.     
  1294.     ViewRect( viewr);
  1295. #ifdef DBUG
  1296.     return true;        // !! SectRect always false for WIN_MOTIF !!!!!        
  1297. #else
  1298.     Boolean visible= Nlm_SectRect( &selr, &viewr, &rct);
  1299.     return visible;
  1300. #endif
  1301. }
  1302.  
  1303. void DRichView::MapView2Doc( Nlm_RecT& selr)
  1304. {
  1305.     short        xoff, yoff;
  1306.     
  1307.     Doc2ViewOffset(xoff, yoff);
  1308.     selr.left         += xoff;
  1309.     selr.right     += xoff;
  1310.     selr.top         += yoff;
  1311.     selr.bottom += yoff;
  1312. }
  1313.     
  1314. void DRichView::MapView2Doc( Nlm_PoinT& mpt)
  1315. {
  1316.     short        xoff, yoff;
  1317.     
  1318.     Doc2ViewOffset(xoff, yoff);
  1319.     mpt.x         += xoff;
  1320.     mpt.y         += yoff;
  1321. }
  1322.  
  1323.  
  1324. Boolean    DRichView::HiliteText(short startparag, short startchar, 
  1325.                                                             short endparag, short endchar, Boolean turnon) 
  1326.             // Finds the visible region of an startparag in a document
  1327.   short             firstItem, fstLine, itemNum, leadHeight,lineHeight, numRows, off;
  1328.   Nlm_RecT         viewr, rct;
  1329.   Boolean              goOn, rsult;
  1330.   Nlm_BaR          sb;
  1331.   DParagraph*      itemPtr;
  1332.  
  1333.   rsult = FALSE;
  1334.      //top = 0;
  1335.      //bottom = 0;
  1336.   //firstline = 0;
  1337.  
  1338.     ViewRect( viewr);
  1339.   sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) fPanel);
  1340.   if (sb) off = Nlm_GetValue(sb);
  1341.   else off= 0;
  1342.   if (startparag >= 0 && startparag < fNumItems) {
  1343.     goOn = TRUE;
  1344.     Nlm_LoadRect(&rct, viewr.left, viewr.top, viewr.right, viewr.top);
  1345.     itemNum = GetItemNum( off);
  1346.     itemPtr = GetParaPtr( itemNum);
  1347.     if (itemPtr) {
  1348.       fstLine = off - itemPtr->startsAt;
  1349.       firstItem = itemNum;
  1350.       lineHeight = 0;
  1351.       leadHeight = 0;
  1352.       numRows = 0;
  1353.       while (goOn && itemNum < fNumItems && itemNum <= startparag) {
  1354.         itemPtr = GetParaPtr( itemNum);
  1355.         if (itemPtr) {
  1356.           CacheIfNever( itemNum + 1, itemPtr, &viewr);
  1357.           if (itemNum > firstItem)  
  1358.             leadHeight = itemPtr->leadHeight;
  1359.             else  
  1360.             leadHeight = 0;
  1361.               if (fstLine==0) rct.top += itemPtr->spaceBefore;
  1362.           
  1363.           lineHeight = itemPtr->lineHeight;
  1364.           rct.top += leadHeight;
  1365.           numRows = MIN (itemPtr->numRows,
  1366.                          MAX ((viewr.bottom - rct.top) / lineHeight, 0));
  1367.           rct.bottom = rct.top + lineHeight * (numRows - fstLine);
  1368.               rct.bottom += itemPtr->spaceAfter;
  1369.           if (itemNum == startparag) {
  1370.             //goOn = FALSE;
  1371.             if (numRows > 0) {
  1372.                 //top = rct.top;
  1373.                 //bottom = rct.bottom;
  1374.                 //firstline = fstLine;
  1375.                 fSelRect.top= rct.top;
  1376.                 fSelRect.bottom= rct.bottom;
  1377.                 //gMapOfs
  1378.                 fSelRect.left= rct.left; // this is bogus, just is left edge...
  1379.                 fSelRect.right= rct.right; // this also is bogus
  1380.               rsult = TRUE;
  1381.                 }
  1382.               } 
  1383.           else  
  1384.             rct.top = rct.bottom;
  1385.           if (numRows < itemPtr->numRows)  
  1386.             goOn = FALSE;
  1387.             }
  1388.         itemNum++;
  1389.         fstLine = 0;
  1390.           }
  1391.         }
  1392.       }
  1393.     fSelRect.bottom= rct.bottom; //????
  1394.      MapView2Doc( fSelRect); //?? need to get it working ??
  1395.   return rsult;
  1396. }
  1397.  
  1398.  
  1399.  
  1400.  
  1401. void DRichView::HiliteSelection(Boolean turnon)
  1402. {
  1403.     if (fSelected) {
  1404.         Nlm_RecT viewr, selr;
  1405.         
  1406.         selr= fSelRect;
  1407.         Boolean visible= MapDoc2View( selr);
  1408.         // !! must map sel location to current view (w/ sb) and see if it
  1409.         // is in view window !!
  1410.         
  1411.         if (!visible) 
  1412.             return;
  1413.         else {
  1414.                 // getting cases where this is called when this view's window is NOT front
  1415.             //DWindow* savewin=  gWindowManager->SavePort(this);
  1416.             if (fSelInPict) {
  1417.                 //Nlm_InvertRect( &selr);
  1418.                 Nlm_InvertMode();
  1419.                 Nlm_FrameRect( &selr);
  1420.                 Nlm_CopyMode();
  1421.                 }
  1422.             else {
  1423.                 ViewRect( viewr);
  1424.                 selr.left= viewr.left;
  1425.                 selr.right= viewr.right;
  1426.                 selr.top= MAX( viewr.top, selr.top - 20);  // expand inval area for full line
  1427.                 selr.bottom = MIN( viewr.bottom, selr.bottom ); 
  1428.                 InvalRect( selr); // let DrawStyledItem do work ?
  1429.                 Boolean savesel= fSelected;
  1430.                 fSelected= turnon;
  1431.                 Nlm_Update();  // this->Draw();
  1432.                 fSelected= savesel;
  1433.                 }
  1434.             //if (savewin) gWindowManager->RestorePort(savewin);
  1435.             }
  1436.         }
  1437. }
  1438.  
  1439. void DRichView::ClearSelection()
  1440. {
  1441.         //?? before unHilite to cure draw bug ??
  1442.     fSelParag= fSelChar= fSelEndParag= fSelEndChar= 0;
  1443.     HiliteSelection(false);
  1444.     //fSelParag= fSelChar= fSelEndParag= fSelEndChar= 0;
  1445.     fSelInPict= false;
  1446.     fSelected= false;
  1447. }
  1448.  
  1449.  
  1450. void DRichView::SetSelectedText( short startparag, short startchar, 
  1451.                                                                     short endparag, short endchar)
  1452. {
  1453.     ClearSelection(); // clear any old sel -- i.e., wipe view markings
  1454.     fSelInPict= false; //!! check if selrect is in a picture !!
  1455.     fSelParag    = Max(0, Min(startparag, fNumItems));      
  1456.     fSelChar    = Max(0, startchar);          // check max !? 
  1457.     
  1458.     fSelEndParag    = Max(0, Min(endparag, fNumItems));      
  1459.     // if endchar==0 endchar== maxchar ??
  1460.     fSelEndChar      = Max(0, endchar);     // check max !? 
  1461.     fSelected= (fSelParag > 0 || fSelChar > 0 || fSelEndChar > 0);
  1462.  
  1463.             // !! NEED THIS parag/char -> fSelRect mapper !!
  1464.     if (HiliteText( fSelParag, fSelChar, fSelEndParag, fSelEndChar, false) ) ;
  1465.  
  1466.     HiliteSelection(fSelected);
  1467. }
  1468.  
  1469. void DRichView::SelectAll()
  1470. {
  1471.     short                    itemNum, leadHeight, atline;
  1472.   Nlm_RecT            viewr, rct;
  1473.   DParagraph*      itemPtr;
  1474.     
  1475.     ClearSelection(); // clear any old sel -- i.e., wipe view markings
  1476.     ViewRect( viewr);
  1477.     Nlm_LoadRect( &rct, 0, 0, viewr.right - viewr.left, 0);
  1478.     atline = 0;
  1479.     leadHeight = 0; 
  1480.     itemNum = 0; //= GetItemNum( atline);
  1481.     while (itemNum < fNumItems) {
  1482.         itemPtr = GetParaPtr( itemNum);
  1483.       if (itemPtr) {
  1484.       CacheIfNever( itemNum + 1, itemPtr, &viewr); // this counts item->numRows
  1485.       if (atline>0) rct.bottom += itemPtr->spaceBefore; 
  1486.       rct.bottom += leadHeight  
  1487.                               + itemPtr->lineHeight * (itemPtr->numRows) 
  1488.                               + itemPtr->spaceAfter;
  1489.            leadHeight = itemPtr->leadHeight;
  1490.           atline += itemPtr->numRows;
  1491.             }
  1492.         itemNum++;
  1493.         }
  1494.  
  1495.     fSelRect= rct;  
  1496.     //MapView2Doc( fSelRect);
  1497.     fSelInPict= false; //!! check if selrect is in a picture !!
  1498.     fSelParag= 1;     // parag # are +1 from MapPoint !!
  1499.     fSelChar= 0;      
  1500.     fSelEndParag= fNumItems;         // parag # are +1 of item# from MapPoint !!
  1501.     fSelEndChar= 0;       
  1502.     fSelected= (fSelParag > 0 && fSelEndParag > 0);
  1503.     HiliteSelection(fSelected);
  1504. }
  1505.  
  1506.  
  1507. void DRichView::MarkSelection( Nlm_RecT selrect)
  1508. {
  1509.     Nlm_PoinT pt;
  1510.     short            row, parag;
  1511.     Nlm_RecT    arect;
  1512.     char            word[50];
  1513.     
  1514.     ClearSelection(); // clear any old sel -- i.e., wipe view markings
  1515.     fSelRect= selrect; // ?? don't we need to map selrect in view coords to doc coords !?
  1516.     MapView2Doc( fSelRect);
  1517.     fSelInPict= false; //!! check if selrect is in a picture !!
  1518.  
  1519.     pt.x= selrect.left;
  1520.     pt.y= selrect.top;
  1521.     MapPoint( pt, parag, row, &arect, word, 40, &fSelStyle);
  1522.     fSelParag= parag;     // parag # are +1 from MapPoint !!
  1523.     fSelChar= gMapOfs;     // dang global... fix mappoint to return it!
  1524.                         // fSelChar was correct
  1525.     if (fSelStyle.ispict) {
  1526.         fSelInPict= true;
  1527.             // ??? must make fSelRect relative to pict frame
  1528.         //fSelRect.left -= fDrawr.left;
  1529.         //fSelRect.right -= fDrawr.left;
  1530.         //fSelRect.top -= fDrawr.top;
  1531.         //fSelRect.bottom -= fDrawr.top;
  1532.         fSelEndParag= 0;
  1533.         fSelEndChar= 0;
  1534.         fSelected= (fSelParag > 0);
  1535.         }
  1536.     else {    
  1537.         pt.x= selrect.right;
  1538.         pt.y= selrect.bottom;
  1539.         MapPoint( pt, parag, row, &arect, word, 40, NULL);
  1540.         fSelEndParag= parag;         // parag # are +1 of item# from MapPoint !!
  1541.         fSelEndChar= gMapOfs;      // fSelEndChar is too large ???
  1542.         fSelected= (fSelParag > 0 && fSelEndParag > 0);
  1543.         }
  1544.     HiliteSelection(fSelected);
  1545. }
  1546.  
  1547.  
  1548. Boolean DRichView::GetSelection( Boolean& inpict,
  1549.                     short& selparag, short& selchar, 
  1550.                     short& selendparag, short& selendchar,
  1551.                     Nlm_RecT& selrect, DRichStyle* selstyle)
  1552. {
  1553.     inpict= fSelInPict;
  1554.     selparag= fSelParag - 1; // !!!!!! FIX DAMN +1 used above !!!!!!
  1555.     selchar= fSelChar;
  1556.     selendparag= fSelEndParag - 1; // !!!!!! FIX DAMN +1 used above !!!!!!
  1557.     selendchar= fSelEndChar;
  1558.     selrect= fSelRect; // !? must we map from doc coords to view coords ??
  1559.     if (selstyle) { *selstyle = fSelStyle; } //style at start of selection (for pict !?)
  1560.     return fSelected;
  1561. }
  1562.  
  1563. char* DRichView::GetSelectedText()
  1564. {
  1565.     long startp, endp, startc, endc;
  1566.     char* theText= NULL;
  1567.  
  1568.     if (fSelInPict) {
  1569.         return NULL; // for now, fix to copy pict to system clipboard
  1570.         }
  1571.         
  1572.     if (fSelParag) {
  1573.         // if selection == NULL ?? return all of text ????
  1574.         startp= fSelParag - 1; 
  1575.         endp= fSelEndParag - 1;
  1576.         startc= fSelChar;
  1577.         endc= fSelEndChar;
  1578.         }
  1579.     else {
  1580.         startp= 0; 
  1581.         endp= fNumItems-1;
  1582.         startc= 0;
  1583.         endc= 0;
  1584.         }
  1585.     
  1586.     for (short par= startp; par<= endp; par++) {
  1587.             // need to handle start/end chars ...
  1588.         DParagraph* itemPtr = GetParaPtr( par);
  1589.         if (itemPtr) {
  1590.             Boolean first= (par == startp);
  1591.             Boolean last = (par == endp);
  1592.             char  savec = 0;
  1593.             char* partext= (char*) itemPtr->fDataPtr;
  1594. #if 1
  1595.             if (first) partext += startc;
  1596.             if (last && endc) {
  1597.                 savec= partext[endc+1];
  1598.                 partext[endc+1]= 0;
  1599.                 }
  1600. #endif
  1601.             if (theText) StrExtendCat( &theText, partext);
  1602.             else theText= StrDup( partext);
  1603.             StrExtendCat( &theText, LINEEND); // append newline for each parag ?
  1604.             if (savec) partext[endc+1]= savec;
  1605.             }
  1606.         }
  1607.          
  1608.     return theText;
  1609. }
  1610.  
  1611.  
  1612.  
  1613. short DRichView::UpdateLineStarts(short first)
  1614. {
  1615.             //  Recalculates the first lines as a running sum of the number of rows
  1616.   short     i;
  1617.   DParagraph*  itemPtr;
  1618.   short     totalNumLines;
  1619.  
  1620.   totalNumLines = 0;
  1621.     itemPtr  = GetParaPtr( first);
  1622.   if (itemPtr) totalNumLines = itemPtr->startsAt;
  1623.   for (i = first; i < fNumItems; i++) {
  1624.     itemPtr = GetParaPtr( i);
  1625.     if (itemPtr) {
  1626.       itemPtr->startsAt = totalNumLines;
  1627.       totalNumLines += itemPtr->numRows;
  1628.         }
  1629.       }
  1630.   return totalNumLines;
  1631. }
  1632.  
  1633.  
  1634. void DRichView::CollectRange(short item, short& lowest, short& highest)
  1635. {
  1636.   lowest  = MIN(lowest, item);
  1637.   highest = MAX(highest, item);
  1638. }
  1639.  
  1640.  
  1641.  
  1642. void DRichView::CacheAndFormat(short item, DParagraph* itemPtr, Nlm_RectPtr r)
  1643. {
  1644.                 //  Formats text (for drawing) if the item text is not currently cached
  1645.   if (itemPtr && r && itemPtr->notCached) FormatText(item, itemPtr, TRUE);
  1646. }
  1647.  
  1648. void DRichView::CacheIfNever( short item, DParagraph* itemPtr, Nlm_RectPtr r)
  1649. {
  1650.         //     Formats text (for obtaining the correct number of rows) if the item
  1651.         //     text has never been cached
  1652.   if (itemPtr && r && itemPtr->neverCached) FormatText(item, itemPtr, TRUE);
  1653. }
  1654.  
  1655.  
  1656. void DRichView::FreeCachedItem( short item, short& lowest, short& highest)
  1657. {
  1658.         // Frees the formatted text string for an item that is not currently visible
  1659.   DParagraph*  itemPtr = GetParaPtr( item);
  1660.   if (itemPtr) {
  1661.     itemPtr->fText = (char*) MemFree (itemPtr->fText);
  1662.     itemPtr->notCached = TRUE;
  1663.     if (fIsVirtual && fNumItems > 0) {
  1664.       itemPtr->numRows = 30000 / fNumItems;
  1665.       CollectRange(item, lowest, highest);
  1666.         }
  1667.       }
  1668. }
  1669.  
  1670.  
  1671. short DRichView::VisLinesAbove(Nlm_RectPtr r, short item,
  1672.                            short line, short& lowest, short& highest)
  1673. {
  1674.         //    Returns the number of lines visible on the screen if the given line
  1675.         //    in the given item is the last line visible
  1676.   DParagraph*  itemPtr;
  1677.   short     pixels, vis;
  1678.  
  1679.   vis = 0;
  1680.   if ( r && item < fNumItems) {
  1681.     pixels = r->bottom - r->top;
  1682.     while (pixels > 0 && item >= 0) {
  1683.       itemPtr = GetParaPtr( item);
  1684.       if (itemPtr) {
  1685.         CollectRange( item, lowest, highest);
  1686.         CacheIfNever( item + 1, itemPtr, r);
  1687.         if (line < 0)  line = itemPtr->numRows - 1;
  1688.         while (pixels > 0 && line >= 0 && line < itemPtr->numRows) {
  1689.           pixels -= itemPtr->lineHeight;
  1690.           if (pixels >= 0)  vis++;
  1691.           line--;
  1692.             }
  1693.         pixels -= itemPtr->leadHeight;
  1694.         pixels -= itemPtr->spaceBefore + itemPtr->spaceAfter;
  1695.           }
  1696.       item--;
  1697.         }
  1698.       }
  1699.   return vis;
  1700. }
  1701.  
  1702.  
  1703.  
  1704. short DRichView::VisLinesBelow( Nlm_RectPtr r, short item,
  1705.                                        short line, short& lowest, short& highest)
  1706. {
  1707.         //    Returns the number of lines visible on the screen if the given line
  1708.         //    in the given item is the first line visible
  1709.   DParagraph*  itemPtr;
  1710.   short     pixels, vis;
  1711.  
  1712.   vis = 0;
  1713.   if (r && item < fNumItems && item >= 0) {
  1714.     pixels = r->bottom - r->top;
  1715.     while (pixels > 0 && item < fNumItems) {
  1716.       itemPtr = GetParaPtr( item);
  1717.       if (itemPtr) {
  1718.         CollectRange(item, lowest, highest);
  1719.         CacheIfNever(item + 1, itemPtr, r);
  1720.         if (line  < 0) {
  1721.           line = 0;
  1722.           pixels -= itemPtr->leadHeight;
  1723.             pixels -= itemPtr->spaceBefore + itemPtr->spaceAfter;
  1724.             }
  1725.         while (pixels > 0 && line >= 0 && line < itemPtr->numRows) {
  1726.           pixels -= itemPtr->lineHeight;
  1727.           if (pixels >= 0) vis++;
  1728.           line++;
  1729.             }
  1730.         line = -1;
  1731.           }
  1732.       item++;
  1733.         }
  1734.       }
  1735.   return vis;
  1736. }
  1737.  
  1738.  
  1739.  
  1740. short DRichView::PixelsBetween( Nlm_RectPtr r, short firstLine,
  1741.                            short lastLine, short& lowest, short& highest)
  1742. {
  1743.              //   Returns the number of pixels between two lines
  1744.      short     count;
  1745.   short     item;
  1746.   DParagraph*  itemPtr;
  1747.   short     line;
  1748.   short     numLines;
  1749.   short     onItem;
  1750.   short     pixels;
  1751.  
  1752.   pixels = 0;
  1753.   if ( r ) {
  1754.       // dgg -- are these line no.s off by one??  came from Scroll()
  1755.       // firstLine--; lastLine--;
  1756.     count = ABS (lastLine - firstLine);
  1757.     item = GetItemNum( MIN (firstLine, lastLine));
  1758.     itemPtr = GetParaPtr( item);
  1759.     onItem = item;
  1760.     if (itemPtr != NULL && item >= 0) {
  1761.       CollectRange( item, lowest, highest);
  1762.       CacheIfNever( item + 1, itemPtr, r);
  1763.       line = MIN (firstLine, lastLine) - itemPtr->startsAt;
  1764.       while (count > 0 && item < fNumItems) {
  1765.         if (item != onItem) {
  1766.           itemPtr = GetParaPtr( item);
  1767.           onItem = item;
  1768.             }
  1769.         if ( itemPtr ) {
  1770.           CollectRange (item, lowest, highest);
  1771.           CacheIfNever ( item + 1, itemPtr, r);
  1772.           numLines = itemPtr->numRows;
  1773. #if 1
  1774.                     if (line == 0) pixels += itemPtr->spaceBefore;
  1775.                     if (MAX(firstLine,lastLine) >= numLines + itemPtr->startsAt)
  1776.                         pixels += itemPtr->spaceAfter;
  1777. #else
  1778.         // ?? old here is bad -- don't do spaceBefore unless this is 1st line in parag
  1779.         // likewise spaceafter if this is last
  1780.                 pixels += itemPtr->spaceBefore + itemPtr->spaceAfter;  
  1781. #endif
  1782.           while (count > 0 && line >= 0 && line < numLines) {
  1783.             pixels += itemPtr->lineHeight;
  1784.             line++;
  1785.             count--;
  1786.               }
  1787.             }
  1788.         item++;
  1789.         if (line >= numLines) {
  1790.           itemPtr = GetParaPtr( item);
  1791.           onItem = item;
  1792.           if (itemPtr != NULL) {
  1793.             CollectRange (item, lowest, highest);
  1794.             CacheIfNever ( item + 1, itemPtr, r);
  1795.             pixels += itemPtr->leadHeight;
  1796.               }
  1797.             }
  1798.         line = 0;
  1799.           }
  1800.       if (lastLine < firstLine)  pixels = -pixels;
  1801.         }
  1802.       }
  1803.   return pixels;
  1804. }
  1805.  
  1806.  
  1807.  
  1808. void DRichView::Draw()
  1809. {
  1810.             //    Panel callback that traverses the item list and draws visible items
  1811.             //    Clipping is to the intersection of the Nlm_updateRgn (the portion of the
  1812.             //    panel exposed) and the inset area of the document, leaving a four-
  1813.             //    pixel margin
  1814.  
  1815.   Nlm_RegioN   dst;
  1816.   DParagraph*  itemPtr;
  1817.   short          firstLine, highest, item, lowest, off, pixels;
  1818.   Nlm_RecT     r, rct;
  1819.   Nlm_BaR      sb;
  1820.   Nlm_RegioN   src;
  1821.  
  1822.   if (fNumItems > 0) {
  1823. //Debug("DRichView::Draw\n");
  1824.         ViewRect( r);
  1825.     sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) fPanel);
  1826.         if (sb) off = Nlm_GetValue(sb);
  1827.         else off= 0;
  1828.     src = Nlm_CreateRgn ();
  1829.     dst = Nlm_CreateRgn ();
  1830.     Nlm_LoadRectRgn (src, r.left, r.top, r.right, r.bottom);
  1831.     Nlm_SectRgn (src, Nlm_updateRgn, dst);
  1832.     Nlm_ClipRgn (dst);
  1833.     Nlm_DestroyRgn (src);
  1834.     Nlm_DestroyRgn (dst);
  1835.     pixels = 0;
  1836.     lowest = 30000; //INT2_MAX; // change for mswin - need??
  1837.         highest = -10000; //INT2_MIN;
  1838.     item = GetItemNum( off);
  1839.     itemPtr = GetParaPtr( item);
  1840.     if (itemPtr) {
  1841.       firstLine = off - itemPtr->startsAt;
  1842.       do {
  1843.         if (itemPtr) {
  1844.           if (itemPtr->neverCached)  CollectRange(item, lowest, highest);
  1845.           CacheAndFormat( item+1, itemPtr, &r);
  1846.           if (pixels != 0)  r.top += itemPtr->leadHeight;
  1847.                   if (firstLine == 0) r.top += itemPtr->spaceBefore;
  1848.           rct = r;
  1849.           rct.bottom = rct.top + itemPtr->lineHeight * (itemPtr->numRows - firstLine);
  1850.           Boolean inrgn= (Nlm_updateRgn == NULL || Nlm_RectInRgn (&rct, Nlm_updateRgn));
  1851.           if (inrgn) {
  1852. //Debug(".");
  1853.             pixels = DrawStyledItem( itemPtr, &r, item+1, firstLine, FALSE, NULL);
  1854.               } 
  1855.           else  
  1856.             pixels = rct.bottom - rct.top;
  1857.            
  1858.           r.top += pixels;
  1859.                   r.top += itemPtr->spaceAfter;
  1860.             }
  1861.         item++;
  1862.         firstLine = 0;
  1863.         itemPtr = GetParaPtr( item);
  1864.       } while (r.top < r.bottom && item < fNumItems);
  1865.       if (lowest < INT2_MAX) 
  1866.         fNumLines = UpdateLineStarts( lowest);
  1867.      
  1868.     }
  1869.     Nlm_ResetClip ();
  1870.      
  1871.   }
  1872.     Nlm_SelectFont(Nlm_programFont);  //Nlm_systemFont
  1873. //Debug("DRichView::Draw done\n");
  1874. }
  1875.  
  1876.  
  1877.  
  1878.  
  1879.  
  1880.  
  1881.  
  1882.  
  1883. void  DRichView::AdjustScroll() 
  1884. {
  1885.             // Calculates an estimate for the scroll bar maximum
  1886.   short     barmax,barval,firstShown,highest, item;
  1887.   short     line,lineInto,lowest;
  1888.   short     pgDn, pgUp, vis;
  1889.   DParagraph*  itemPtr;
  1890.   Nlm_RecT     r;
  1891.   Nlm_BaR      sb;
  1892.  
  1893.   sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) fPanel);
  1894.   if (sb) {
  1895.     if (fNumLines > 0 && fNumItems > 0) {
  1896.           Nlm_SelectFont(Nlm_programFont);  //Nlm_systemFont
  1897.             ViewRect( r);
  1898.       barval = Nlm_GetValue (sb);
  1899.       item = GetItemNum ( barval);
  1900.       line = barval - GetLineStart( item);
  1901.       firstShown = item;
  1902.       lineInto = line;
  1903.       lowest = INT2_MAX;
  1904.       highest = INT2_MIN;
  1905.       itemPtr = GetParaPtr(fNumItems - 1);
  1906.       if (itemPtr) 
  1907.         vis = VisLinesAbove ( &r, fNumItems - 1,
  1908.                              itemPtr->numRows - 1, lowest, highest);
  1909.       pgUp = VisLinesAbove ( &r, item, line, lowest, highest) - 1;
  1910.       pgDn = VisLinesBelow ( &r, item, line, lowest, highest) - 1;
  1911.       if (pgDn < 1) pgDn = 1;
  1912.       if (pgUp < 1) pgUp = 1;
  1913.       if (lowest < INT2_MAX) 
  1914.         fNumLines = UpdateLineStarts( lowest);
  1915.       
  1916.       itemPtr = GetParaPtr(fNumItems - 1);
  1917.       if (itemPtr) {
  1918.         barmax = 0;
  1919.               ViewRect( r);
  1920.         lowest = INT2_MAX;
  1921.         highest = INT2_MIN;
  1922.         vis = VisLinesAbove ( &r, fNumItems - 1,
  1923.                              itemPtr->numRows - 1, lowest,  highest);
  1924.         if (lowest < INT2_MAX) 
  1925.           fNumLines = UpdateLineStarts ( lowest);
  1926.          
  1927.         barmax = fNumLines - vis;
  1928.         barval = GetLineStart(firstShown) + lineInto;
  1929.         Nlm_CorrectBarPage (sb, pgUp, pgDn);
  1930.         if (barval > fBarmax) {
  1931.           Nlm_CorrectBarMax (sb, barmax);
  1932.           Nlm_CorrectBarValue (sb, barval);
  1933.             } 
  1934.         else {
  1935.           Nlm_CorrectBarValue (sb, barval);
  1936.           Nlm_CorrectBarMax (sb, barmax);
  1937.             }
  1938.         fBarmax = barmax;
  1939.           }
  1940.         } 
  1941.     else  
  1942.       Nlm_Reset (sb);
  1943.       }
  1944. }
  1945.  
  1946.  
  1947.  
  1948.  
  1949.  
  1950.  
  1951. void  DRichView::UpdateItemHeights(DParagraph* aParag)
  1952. {
  1953.             // Returns the maximum height of all fonts used in an item
  1954.   short         i, linhgt,maxhgt;
  1955.  
  1956.   if (aParag) {
  1957.     maxhgt = 0;
  1958.     i = aParag->fNumStyles;
  1959.     while (i > 0) {
  1960.       i--;
  1961.       DRichStyle* st= GetStyleAtIndex(aParag, i);
  1962.            linhgt = GetFontHeight(st->font) + abs(st->superSub); 
  1963.       if (st->ispict) 
  1964.                  linhgt = MAX(linhgt, st->pixheight + 2); // +2 for leading !?
  1965.       if (linhgt > maxhgt) maxhgt = linhgt;
  1966.         }
  1967.     if (maxhgt == 0)  maxhgt = Nlm_stdLineHeight;
  1968.     aParag->lineHeight = MAX(maxhgt, aParag->minHeight);
  1969.     if ( aParag->openSpace)  
  1970.       aParag->leadHeight = maxhgt;
  1971.     else 
  1972.       aParag->leadHeight = 0;
  1973.       }
  1974. }
  1975.  
  1976.  
  1977. short DRichView::SkipPastNewLine(char* text, short cnt)
  1978. {
  1979.   char  ch;
  1980.   ch = *(text + cnt);
  1981.   while (ch != '\0' && ch != '\n' && cnt < 16380) {
  1982.     cnt++;
  1983.     ch = *(text + cnt);
  1984.       }
  1985.   while ((ch == '\n' || ch == '\r') && cnt < 16380) {
  1986.     cnt++;
  1987.     ch = *(text + cnt);
  1988.       }
  1989.   return cnt;
  1990. }
  1991.  
  1992. void     DRichView::HandleAddInsRep( handleMode mode, short item, char* text, 
  1993.                     DParagraph* parFormat, DRichStyle* styles, short nstyles, Nlm_FonT aFont) 
  1994. {
  1995.     DRichStyle    * aStyle = NULL;
  1996.   DParagraph     * para = NULL;
  1997.     
  1998.     if (!parFormat) {
  1999.         para= new DParagraph();
  2000.         parFormat= para;
  2001.         }
  2002.     
  2003.     if (!styles) {
  2004.         aStyle= new DRichStyle();
  2005.         if (aFont) aStyle->font= aFont;
  2006.         aStyle->last= true;
  2007.         styles= aStyle;
  2008.         nstyles= 1;
  2009.         }
  2010.         
  2011.     if (text && *text != '\0') {
  2012.       long start = 0;
  2013.       short atstyle= 0;
  2014.       long cntr = StringLen (text);
  2015.       long cnt = MIN (cntr, 16000);
  2016.       cnt = SkipPastNewLine (text + start, cnt);
  2017.       while (cnt > 0) {
  2018.         char* txt = (char*) MemNew(cnt + 1);
  2019.         MemCopy(txt, text + start, cnt);
  2020.         
  2021.         // damn !!! have to fiddle w/ styles[...].nextofs for this newline cutting stuff !!
  2022.         short ist= atstyle, nst= 0;
  2023.         if (nstyles) {
  2024.             do ist++; 
  2025.             while (ist<nstyles && styles[ist].nextofs <= start + cnt);
  2026.             nst= ist - atstyle;     
  2027.             }
  2028.             
  2029.         switch (mode) {
  2030.             case kAppend: 
  2031.                 Append( txt, (cnt / 50) + 1, parFormat, &styles[atstyle], nst, true);
  2032.                 break;
  2033.             case kReplace:
  2034.                     Replace( item, txt, (cnt / 50) + 1, parFormat, &styles[atstyle], nst, true);
  2035.                 break;
  2036.             case kInsert:
  2037.                     Insert( item, txt, (cnt / 50) + 1, parFormat, &styles[atstyle], nst, true);
  2038.                 break;
  2039.             }
  2040.             
  2041.         atstyle += nst - 1;
  2042.         start += cnt;
  2043.         cntr -= cnt;
  2044.         cnt = MIN (cntr, 16000);
  2045.         cnt = SkipPastNewLine (text + start, cnt);
  2046.           }
  2047.         } 
  2048.     else switch (mode) {
  2049.       case kAppend: 
  2050.             Append( "", 1, parFormat, styles, nstyles, false);
  2051.           break;
  2052.       case kReplace:
  2053.             Replace( item, "", 1, parFormat, styles, nstyles, false);
  2054.           break;
  2055.         case kInsert:
  2056.             Insert( item, "", 1, parFormat, styles, nstyles, false);
  2057.           break;
  2058.       }
  2059.       
  2060.   if (para) delete para;
  2061.   //if (aStyle) delete aStyle;
  2062. }
  2063.  
  2064.  
  2065. void     DRichView::Append( char* text, DParagraph* parFormat, DRichStyle* styles, 
  2066.                     short nstyles, Nlm_FonT aFont) 
  2067. {
  2068.     HandleAddInsRep( kAppend, 0,  text, parFormat, styles, nstyles, aFont);
  2069. }
  2070.  
  2071. void     DRichView::Replace( short item, char* text, DParagraph* parFormat, 
  2072.                                 DRichStyle* styles, short nstyles, Nlm_FonT aFont) 
  2073. {
  2074.     HandleAddInsRep( kReplace, item, text, parFormat, styles, nstyles, aFont);
  2075. }
  2076.  
  2077. void     DRichView::Insert( short item, char* text, DParagraph* parFormat,
  2078.              DRichStyle* styles, short nstyles, Nlm_FonT aFont) 
  2079. {
  2080.     HandleAddInsRep( kInsert, item, text, parFormat, styles, nstyles, aFont);
  2081. }
  2082.  
  2083.  
  2084.  
  2085. void  DRichView::Delete( short item) 
  2086. {
  2087.                 //  Deletes an item from a document
  2088.   if (item >= 0 && item < fNumItems) {
  2089.         fParags->AtDelete(item);
  2090.     fNumItems = fParags->GetSize(); 
  2091.     fNumLines = UpdateLineStarts( item);
  2092.     if (fAutoAdjust) AdjustScroll();
  2093.     }
  2094. }
  2095.  
  2096.  
  2097. void  DRichView::GetDocStats( short& numParags, short& numLines) 
  2098. {
  2099.   numParags = fNumItems;
  2100.   numLines = fNumLines;  
  2101. }
  2102.  
  2103.  
  2104.  
  2105. void  DRichView::GetItemStats( short item, short& startsAt, short& numRows, 
  2106.                                                              short& lineHeight) 
  2107. {
  2108.     DParagraph* itemPtr = GetParaPtr( item );  // item starts at 0
  2109.   if (itemPtr) {
  2110.     startsAt = itemPtr->startsAt;
  2111.     numRows = itemPtr->numRows;
  2112.     lineHeight = itemPtr->lineHeight;
  2113.       }
  2114.   else {
  2115.       startsAt = 0;
  2116.       numRows = 0;
  2117.       lineHeight = 0;  
  2118.       }
  2119. }
  2120.  
  2121.  
  2122.  
  2123.  
  2124.  
  2125. void     DRichView::MapPoint( Nlm_PoinT pt, short& item, short& row, Nlm_RectPtr rct,
  2126.                     char* wordAt, short maxword, DRichStyle* styleAt) 
  2127. {
  2128.                 // Converts a mouse point to a item, row positions  within a document
  2129.   short     cl,firstItem,firstLine;
  2130.   short     itemNum,rw,itm,leadHeight,lineHeight,numRows,off;
  2131.   Boolean      goOn;
  2132.   Nlm_RecT     viewr, paragr, rc;
  2133.   Nlm_BaR      sb;
  2134.   DParagraph*  itemPtr;
  2135.  
  2136.   itm = 0;
  2137.   rw = 0;
  2138.   cl = 0;
  2139.   Nlm_LoadRect (&rc, 0, 0, 0, 0);
  2140.  
  2141.     ViewRect( viewr);
  2142.   if (Nlm_PtInRect (pt, &viewr)) {
  2143.     sb = Nlm_GetSlateVScrollBar ((Nlm_SlatE) fPanel);
  2144.         if (sb) off = Nlm_GetValue(sb);
  2145.         else off= 0;
  2146.     goOn = TRUE;
  2147.     itemNum = GetItemNum( off);
  2148.     itemPtr = GetParaPtr( itemNum);
  2149.     if (itemPtr) {
  2150.             paragr= viewr;
  2151.       firstLine = off - itemPtr->startsAt;
  2152.       firstItem = itemNum;
  2153.       while (goOn && itemNum < fNumItems) {
  2154.         itemPtr = GetParaPtr( itemNum);
  2155.         if (itemPtr) {
  2156.           CacheIfNever( itemNum + 1, itemPtr, ¶gr);
  2157.           if (itemNum > firstItem)  
  2158.             leadHeight = itemPtr->leadHeight;
  2159.             else 
  2160.             leadHeight = 0;
  2161.           if (firstLine==0) paragr.top += itemPtr->spaceBefore;
  2162.        
  2163.           lineHeight = itemPtr->lineHeight;
  2164.           numRows = MIN (itemPtr->numRows - firstLine,
  2165.                          MAX ((viewr.bottom - paragr.top - leadHeight) / lineHeight, 1));
  2166.           paragr.bottom = paragr.top + leadHeight + lineHeight * numRows;
  2167.                paragr.bottom += itemPtr->spaceAfter;
  2168.                
  2169.              if (Nlm_PtInRect(pt, ¶gr) && numRows > 0) {
  2170.             goOn = FALSE;
  2171.             itm = itemNum + 1;
  2172.             if (pt.y <= paragr.top + leadHeight)  
  2173.               rw = 0;
  2174.             else  
  2175.               rw = firstLine + ((pt.y - paragr.top - leadHeight) / lineHeight) + 1;
  2176.  
  2177.               rc = paragr;
  2178.               if (rw) rc.top += (rw-1) * lineHeight;
  2179.               rc.bottom = rc.top + lineHeight;
  2180.               
  2181.             // dgg -- map to style section                 
  2182.             if (wordAt || styleAt) {
  2183.                       short textofs = DrawStyledItem( itemPtr, ¶gr, itm/*itemNum+1*/, 
  2184.                                                   firstLine/*rw*/, FALSE, &pt);
  2185.                             if (wordAt) {
  2186.                                 if (textofs<0) {
  2187.                                     StrNCpy(wordAt, "**not found", maxword);
  2188.                          wordAt[maxword-1]= 0;
  2189.                                     }
  2190.                                 else {
  2191.                                     char *cbase= itemPtr->fText;
  2192.                                     char *cstart= cbase + textofs;
  2193.                                     if (*cstart <= ' ') {
  2194.                                         if (cstart[1] > ' ') cstart++;
  2195.                                         else if (cstart[-1] > ' ') cstart--;
  2196.                                         }
  2197.                                     char *cend= cstart;
  2198.                        while (cstart > cbase && cstart[-1] > ' ') cstart--;
  2199.                           while (*cend > ' ') cend++;
  2200.                        short len= MAX(1, MIN( maxword-1, cend - cstart));
  2201.                          StrNCpy(wordAt, cstart, len);
  2202.                          wordAt[len]= 0;
  2203.                          }
  2204.                        }
  2205.               if (styleAt && fMapStyle) {
  2206.                   *styleAt= *fMapStyle; // GetStyleAtChar( itemPtr, textofs);
  2207.                   }
  2208.                    }
  2209.                    
  2210.               } 
  2211.           else  
  2212.             paragr.top = paragr.bottom;
  2213.            
  2214.           if (numRows < itemPtr->numRows - firstLine)  
  2215.             goOn = FALSE;
  2216.             }
  2217.         itemNum++;
  2218.         firstLine = 0;
  2219.         }
  2220.       }
  2221.     }
  2222.  
  2223.     item = itm;
  2224.     row = rw;
  2225.     if (rct) *rct = rc;
  2226. }
  2227.  
  2228.  
  2229.  
  2230.  
  2231. Boolean DRichView::Find( char* match, short& itemat, short& charat,
  2232.                             short startitem, short startchar, Boolean caseSensitive) 
  2233. {
  2234.   DParagraph*        itemPtr;
  2235.   short            i, stop;
  2236.     
  2237.   if (match) {
  2238.         char* tempmatch= StrDup( match);
  2239.     if (fNumItems > 0) {
  2240.           stop = fNumItems;
  2241.         if (startitem < 0) startitem = 0;
  2242.         for (i = startitem; i < stop; i++) {
  2243.           itemPtr = GetParaPtr( i);
  2244.           if (itemPtr) {
  2245.                          char* text;
  2246.                         text= (char*) itemPtr->fDataPtr;
  2247.             if (text) {
  2248.                             Nlm_Uint4        foundat;
  2249.                             Boolean         found 
  2250.                                     = Nlm_StrngPos(text, tempmatch, startchar, caseSensitive, &foundat);
  2251.               if (found) {
  2252.                   itemat= i;
  2253.                     charat= foundat;
  2254.                                 MemFree( tempmatch);
  2255.                   return TRUE;
  2256.                   }      
  2257.                   }
  2258.               }
  2259.           startchar= 0; // ! zero it !! or we miss others ! 
  2260.           }
  2261.                 }
  2262.         MemFree( tempmatch);
  2263.         }
  2264.     return FALSE;
  2265. }
  2266.  
  2267.  
  2268.  
  2269.  
  2270. Boolean     DRichView::FindURL(short& itemat, short& charat, short& charlen,
  2271.                                                         short startitem, short startchar) 
  2272. {
  2273.   DParagraph*     itemPtr;
  2274.   short            i, stop;
  2275.     
  2276.     if (fNumItems > 0) {
  2277.       stop = fNumItems;
  2278.     if (startitem < 0) startitem = 0;
  2279.     for (i = startitem; i < stop; i++) {
  2280.       itemPtr = GetParaPtr( i);
  2281.       if (itemPtr) {
  2282.                 char* text;
  2283.                 // text= (char*) itemPtr->fDataPtr; << this is bad, need fText !
  2284.                 FormatText( i, itemPtr, TRUE);
  2285.                 text = itemPtr->fText;
  2286.           if (text) {
  2287.                     char             *cp, *ep;
  2288.  
  2289.                     for (cp= text+startchar+3; *cp; cp++) { 
  2290.                         if (*cp == ':') {
  2291.                             if ( (cp[1] == '/' && cp[2] == '/') 
  2292.                                 || (0 == Nlm_StringNICmp( MAX(text, cp-6), "mailto", 6))
  2293.                                 || (0 == Nlm_StringNICmp( MAX(text, cp-4), "news", 4))
  2294.                                 /* ^^^^ Should use DURL::IsURL(cp) !! */
  2295.                                 ) {
  2296.                                   cp--;
  2297.                                     while (isalnum(*cp) && cp>text) cp--;
  2298.                                     if (*cp == '"') ep= strchr(cp+1,'"');
  2299.                                     else if (*cp == '\'') ep= strchr(cp+1,'\'');
  2300.                                     else if (*cp == '<') ep= strchr(cp+1,'>');
  2301.                                     else if (*cp == '=' 
  2302.                                         && 0 == Nlm_StringNICmp( MAX(text,cp-4), "href=", 4 )) 
  2303.                                             ep= strchr(cp+1,'>');
  2304.                                     else ep= NULL;
  2305.                                     if (!isalnum(*cp)) cp++;
  2306.                                   if (ep == NULL) for (ep=cp; isgraph(*ep); ep++) ;
  2307.                       itemat= i;
  2308.                       charat= cp - text;
  2309.                                     charlen= ep ? ep - cp : 0;
  2310.                       return TRUE;
  2311.                       }
  2312.                             } 
  2313.                         }     
  2314.               }
  2315.           }
  2316.       startchar= 0; // ! zero it !! or we miss others ! 
  2317.       }
  2318.         }
  2319.  
  2320.     return FALSE;
  2321. }
  2322.  
  2323.  
  2324.  
  2325.  
  2326.  
  2327. void     DRichView::InsertStyle( short atitem, short atchar, short atlength, 
  2328.                                                             DRichStyle* theStyle)
  2329. {
  2330.   DParagraph*     itemPtr;
  2331.     short                    numStyles;
  2332.     
  2333.     itemPtr = GetParaPtr( atitem);
  2334.   if (theStyle && itemPtr) {
  2335.         short ist, jst;
  2336.         numStyles= itemPtr->fNumStyles;
  2337.         StyleIndex* si = itemPtr->fStyleIndex;
  2338.         short newofs= atchar + atlength;
  2339.         short newnum= numStyles + 2;
  2340.         StyleIndex* sinew=    
  2341.             (StyleIndex*) MemNew( newnum*sizeof(StyleIndex)); 
  2342.  
  2343.         short styleid= FindOrAddStyle(theStyle);
  2344.         Boolean notat= true, notnew= true;
  2345.         for (ist=0, jst= 0; ist<numStyles && jst<newnum; ist++) {
  2346.             short ofs= si[ist].nextofs;
  2347.             
  2348.             if (atchar <= ofs && notat) {
  2349.                 if (atchar < ofs) {
  2350.                     sinew[jst]= si[ist];
  2351.                     sinew[jst].nextofs= atchar;
  2352.                     if (jst<newnum) jst++;
  2353.                     }
  2354.                 else {
  2355.                     sinew[jst]= si[ist];
  2356.                     if (jst<newnum) jst++;
  2357.                     }
  2358.                 sinew[jst].nextofs= newofs;
  2359.                 sinew[jst].styleid= styleid;
  2360.                 if (jst<newnum) jst++;
  2361.                 notat= false;
  2362.                 }
  2363.             else {  // atchar > ofs
  2364.                 sinew[jst]= si[ist];
  2365.                 if (jst<newnum) jst++;
  2366.                 }
  2367.             
  2368.             if (newofs <= ofs && notnew) {
  2369.                 sinew[jst]= si[ist];
  2370.                 if (jst<newnum) jst++;
  2371.                 notnew= false;
  2372.                 }
  2373.             }
  2374.             
  2375.         itemPtr->fStyleIndex= sinew;
  2376.         itemPtr->fNumStyles = jst; // newnum
  2377.         MemFree( si);
  2378.         
  2379.         
  2380.       }
  2381.      
  2382. }
  2383.  
  2384.  
  2385.  
  2386.  
  2387.  
  2388.  
  2389.  
  2390. char* DRichView::GetText(short item, short row) 
  2391. {
  2392.             //   Returns a string with text from a document.  If item, row
  2393.             //   parameters are 0, text is taken from any item, row,
  2394.             //   respectively.  The string must be freed by the application
  2395.   ByteStorePtr      bsp;
  2396.   char              ch;
  2397.   short              cl, i;
  2398.   short              k, num;
  2399.   short              rw, start, stop;
  2400.   char                    * text;
  2401.   char                    * ptr;
  2402.   Nlm_RecT            r;
  2403.   DParagraph*        itemPtr;
  2404.  
  2405.   text = NULL;
  2406.   if (item >= 0) {
  2407.         ViewRect( r);
  2408.     if (fNumItems > 0) {
  2409.       bsp = BSNew (0);
  2410.       if (bsp != NULL) {
  2411.         if (item == 0) {
  2412.           start = 0;
  2413.           stop = fNumItems;
  2414.             } 
  2415.         else if (item <= fNumItems) {
  2416.           start = item - 1;
  2417.           stop = item;
  2418.             } 
  2419.         else {
  2420.           start = 0;
  2421.           stop = 0;
  2422.             }
  2423.  
  2424. #if 1
  2425.             if (row < 0) {
  2426.         itemPtr = GetParaPtr( start);
  2427.         if (itemPtr) {
  2428.                     text= (char*) itemPtr->fDataPtr;
  2429.                       // if (text) text= MemDup(text);   //!? caller expects to own this data !? 
  2430.                     }
  2431.                 return text;
  2432.                 }
  2433. #else
  2434.             if (row < 0) {
  2435.         for (i = start; i < stop; i++) {
  2436.           itemPtr = GetParaPtr( i);
  2437.           if (itemPtr) {
  2438.                       if (!text) text = DataToChar(itemPtr->fDataPtr);
  2439.                         }
  2440.                     }
  2441.                   return text;
  2442.                 }
  2443. #endif
  2444.  
  2445.         for (i = start; i < stop; i++) {
  2446.           itemPtr = GetParaPtr( i);
  2447.           if (itemPtr) {
  2448.                         DParagraph itemData( itemPtr->fDataPtr, false, itemPtr->numRows, itemPtr, 
  2449.                                                 itemPtr->fStyleIndex, itemPtr->fNumStyles, false);
  2450.             FormatText(i, &itemData, TRUE);
  2451.             text = itemData.fText;
  2452.             if (text && *text != '\0') {
  2453.               if (i > start && itemPtr->openSpace > 0 && item == 0) 
  2454.                 BSPutByte (bsp, (short) '\n');
  2455.               rw = 0;
  2456.               cl = 0;
  2457.               ptr = text;
  2458.               ch = *ptr;
  2459.               while (ch != '\0') {
  2460.                 if (ch == '\n') {
  2461.                   if ((rw + 1 == row) || row == 0)  
  2462.                     BSPutByte (bsp, (short) '\n');
  2463.                   cl = 0;
  2464.                   rw++;
  2465.                   ptr++;
  2466.                     } 
  2467.                 else if (ch == '\t') {
  2468.                   if ((rw + 1 == row || row == 0)) 
  2469.                     BSPutByte (bsp, (short) '\t');
  2470.                    
  2471.                   cl++;
  2472.                   ptr++;
  2473.                     } 
  2474.                 else {
  2475.                   num = 0;
  2476.                   while (ch != '\0' && ch != '\t' && ch != '\n') {
  2477.                     num++;
  2478.                     ch = ptr [num];
  2479.                       }
  2480.                   if (num > 0  &&
  2481.                       (rw + 1 == row || row == 0)) {
  2482.                     for (k = 0; k < num; k++) 
  2483.                       BSPutByte (bsp, (short) ptr [k]);
  2484.                     }
  2485.                   ptr += num;
  2486.                     }
  2487.                 ch = *ptr;
  2488.                   }
  2489.                 }
  2490.               }
  2491.             }
  2492.         text = (char*) BSMerge (bsp, NULL);
  2493.         BSFree (bsp);
  2494.           }
  2495.         }
  2496.       }
  2497.   return text;
  2498. }
  2499.  
  2500.  
  2501.  
  2502.  
  2503.  
  2504. Boolean    DRichView::IsVisible( short item, short& top, short& bottom, short& firstline) 
  2505. {
  2506.             // Finds the visible region of an item in a document
  2507.   short             firstItem, fstLine, itemNum, leadHeight,lineHeight, numRows,off;
  2508.   Nlm_RecT         r, rct;
  2509.   Boolean              goOn, rsult;
  2510.   Nlm_BaR          sb;
  2511.   DParagraph*      itemPtr;
  2512.  
  2513.   rsult = FALSE;
  2514.      top = 0;
  2515.      bottom = 0;
  2516.   firstline = 0;
  2517.  
  2518.     ViewRect(  r);
  2519.   sb = Nlm_GetSlateVScrollBar ((Nlm_SlatE) fPanel);
  2520.   if (sb) off = Nlm_GetValue (sb);
  2521.   else off= 0;
  2522.   if (item > 0 && item <= fNumItems) {
  2523.     item--;
  2524.     goOn = TRUE;
  2525.     Nlm_LoadRect (&rct, r.left, r.top, r.right, r.top);
  2526.     itemNum = GetItemNum ( off);
  2527.     itemPtr = GetParaPtr( itemNum);
  2528.     if (itemPtr) {
  2529.       fstLine = off - itemPtr->startsAt;
  2530.       firstItem = itemNum;
  2531.       lineHeight = 0;
  2532.       leadHeight = 0;
  2533.       numRows = 0;
  2534.       while (goOn && itemNum < fNumItems && itemNum <= item) {
  2535.         itemPtr = GetParaPtr( itemNum);
  2536.         if (itemPtr ) {
  2537.           CacheIfNever ( itemNum + 1, itemPtr, &r);
  2538.           if (itemNum > firstItem)  
  2539.             leadHeight = itemPtr->leadHeight;
  2540.             else  
  2541.             leadHeight = 0;
  2542.               if (fstLine==0) rct.top += itemPtr->spaceBefore;
  2543.           
  2544.           lineHeight = itemPtr->lineHeight;
  2545.           rct.top += leadHeight;
  2546.           numRows = MIN (itemPtr->numRows,
  2547.                          MAX ((r.bottom - rct.top) / lineHeight, 0));
  2548.           rct.bottom = rct.top + lineHeight * (numRows - fstLine);
  2549.               rct.bottom += itemPtr->spaceAfter;
  2550.           if (itemNum == item) {
  2551.             goOn = FALSE;
  2552.             if (numRows > 0) {
  2553.                 top = rct.top;
  2554.                 bottom = rct.bottom;
  2555.                 firstline = fstLine;
  2556.               rsult = TRUE;
  2557.                 }
  2558.               } 
  2559.           else  
  2560.             rct.top = rct.bottom;
  2561.           if (numRows < itemPtr->numRows)  
  2562.             goOn = FALSE;
  2563.             }
  2564.         itemNum++;
  2565.         fstLine = 0;
  2566.           }
  2567.         }
  2568.       }
  2569.   
  2570.   return rsult;
  2571. }
  2572.  
  2573.  
  2574.  
  2575.  
  2576.  
  2577. Boolean DRichView::GetScrollStats( short& offset, short& firstShown, short& firstLine) 
  2578. {
  2579.   short     item, line,off;
  2580.   Boolean      rsult;
  2581.   Nlm_BaR        sb;
  2582.  
  2583.   sb = Nlm_GetSlateVScrollBar((Nlm_SlatE)fPanel);
  2584.   if (sb) {
  2585.     off = Nlm_GetValue (sb);
  2586.     item = GetItemNum ( off);
  2587.     line = off - GetLineStart(item);
  2588.     rsult = TRUE;
  2589.       }
  2590.   else {
  2591.       off = 0;
  2592.       item = 0;
  2593.       line = 0;  
  2594.       rsult = FALSE;
  2595.       }
  2596.   offset = off;
  2597.   firstShown = item + 1;
  2598.   firstLine = line;
  2599.   return rsult;
  2600. }
  2601.  
  2602.  
  2603.  
  2604.  
  2605.  
  2606.  
  2607. void  DRichView::Update( short from, short to) 
  2608. {
  2609.             // Invalidates and updates items in a document
  2610.   short         bottom,item,start,stop,swap,top, f1;
  2611.   DParagraph*  itemPtr;
  2612.   Nlm_RecT     r;
  2613.   Nlm_WindoW   tempPort;
  2614.  
  2615.   if (from >= 0 && to >= 0) {
  2616.     if (from == 0 || from > fNumItems) {
  2617.       start = 0;
  2618.       from = 0;
  2619.         } 
  2620.     else  
  2621.       start = from - 1;
  2622.      
  2623.     if (to == 0 || to > fNumItems) 
  2624.       stop = to = fNumItems;
  2625.     else  
  2626.       stop = to;
  2627.     
  2628.     for (item = start; item < stop; item++) {
  2629.       itemPtr = GetParaPtr(item);
  2630.       if (itemPtr) {
  2631.         itemPtr->fText = (char*) MemFree (itemPtr->fText);
  2632.         itemPtr->notCached = TRUE;
  2633.         itemPtr->neverCached = TRUE;
  2634.           }
  2635.         }
  2636.     if (Nlm_Enabled(fPanel) && Nlm_AllParentsEnabled(fPanel) &&
  2637.         Nlm_Visible(fPanel) && Nlm_AllParentsVisible(fPanel)) {
  2638.       tempPort = Nlm_SavePort(fPanel);
  2639.             ViewRect( r);
  2640.       Nlm_Select(fPanel);
  2641.       if (from > to && from != 0 && to != fNumItems) {
  2642.         swap = from;
  2643.         from = to;
  2644.         to = swap;
  2645.           }
  2646.       if (from > 0 && from <= fNumItems && IsVisible( from, top, bottom, f1))  
  2647.         r.top = top;
  2648.       if (to > 0 && to < fNumItems && IsVisible( to, top, bottom, f1))  
  2649.         r.bottom = bottom;
  2650.       Nlm_InsetRect(&r, -1, -1);
  2651.       Nlm_InvalRect(&r);
  2652.       if (tempPort) Nlm_RestorePort(tempPort);
  2653.         }
  2654.     AdjustScroll();
  2655.       }
  2656. }
  2657.  
  2658.  
  2659.  
  2660. void DRichView::SaveTableItem(DParagraph* itemPtr, FILE *f, Boolean tabStops)
  2661. {
  2662.                 //    Reformats and saves an item to a file
  2663.   char         ch;
  2664.   short     i;
  2665.   short     next,num,pos,row;
  2666.   char    *     ptr;
  2667.   char    *        text;
  2668.  
  2669.   next= 0;
  2670.   if (itemPtr && f) {
  2671.     text = itemPtr->fText;
  2672.     if (text && *text != '\0') {
  2673.       pos = 0;
  2674.       row = 0;
  2675.       ptr = text;
  2676.       ch = *ptr;
  2677.       while (ch != '\0') {
  2678.         if (ch == '\n') {
  2679.           row++;
  2680.           ptr++;
  2681.           pos = 0;
  2682.           fputc ('\n', f);
  2683.             } 
  2684.         else  {
  2685.           num = 0;
  2686.           while (ch != '\0' && ch != '\n') {
  2687.             num++;
  2688.             ch = ptr [num];
  2689.               }
  2690.           if (num > 0) {
  2691.             while (num > 0 && *ptr == '\t') {
  2692.               num--;
  2693.               ptr++;
  2694.               next += fTabCount;
  2695.                 }
  2696.             while (pos < next) {
  2697.               fputc (' ', f);
  2698.               pos++;
  2699.                 }
  2700.             for (i = 0; i < num; i++) {
  2701.               fputc (ptr [i], f);
  2702.               pos++;
  2703.                 }
  2704.               }
  2705.           ptr += num;
  2706.             }
  2707.         ch = *ptr;
  2708.       }
  2709.     }
  2710.   }
  2711. }
  2712.  
  2713.  
  2714.  
  2715.  
  2716. void DRichView::Save(DFile* f) 
  2717.   if ( f ) {
  2718.     Boolean savevirt= fIsVirtual;
  2719.     fIsVirtual = FALSE;
  2720.     for (short i = 0; i < fNumItems; i++) {
  2721.       DParagraph* itemPtr = GetParaPtr( i);
  2722.       if (itemPtr) {
  2723.                 DParagraph itemData( itemPtr->fDataPtr, false, itemPtr->numRows, itemPtr, 
  2724.                                         itemPtr->fStyleIndex, itemPtr->fNumStyles, false);
  2725.            FormatText(0, &itemData, FALSE);
  2726.                 if (i > 0 && itemData.openSpace > 0) fputc ('\n', f->fFile);
  2727.            SaveTableItem(&itemData, f->fFile,  TRUE);
  2728.         }
  2729.       }
  2730.         fIsVirtual= savevirt;
  2731.     }
  2732. }
  2733.  
  2734.  
  2735.  
  2736.  
  2737.  
  2738. void DRichView::Print()    
  2739. #if (defined(WIN_MAC) || defined (WIN_MSWIN))
  2740.   Boolean   goOn;
  2741.   short      i, item, line,pixels, visBelow;
  2742.   DParagraph*   itemPtr;
  2743.   Boolean   newPage;
  2744.   Nlm_RecT      r, rct;
  2745.   FloatHi           scale;
  2746.   Nlm_WindoW    w;
  2747.  
  2748.   Boolean savevirt= fIsVirtual;
  2749.   fIsVirtual = FALSE;
  2750.     if (fNumItems > 0) {
  2751.         ViewRect( rct);
  2752.     w = Nlm_StartPrinting ();
  2753.     if (w != NULL) {
  2754.       for (i = 0; i < MAXFONTS; i++) {
  2755.         gFontHeights[i].font = NULL;
  2756.         gFontHeights[i].height = 0;
  2757.           }
  2758.       goOn = TRUE;
  2759.       pixels = 0;
  2760.       item = 0;
  2761.       newPage = TRUE;
  2762.       while (item < fNumItems && goOn) {
  2763.         if (newPage) {
  2764.           goOn = Nlm_StartPage ();
  2765.           newPage = FALSE;
  2766.           Nlm_PrintingRect (&r);
  2767.             }
  2768.         if (goOn) {
  2769.           itemPtr = GetParaPtr( item);
  2770.           if (itemPtr) {
  2771.                         DParagraph itemData( itemPtr->fDataPtr, false, itemPtr->numRows, itemPtr, 
  2772.                                                                 itemPtr->fStyleIndex, itemPtr->fNumStyles, false);
  2773.             UpdateItemHeights (&itemData);
  2774.             scale = (FloatHi) (r.right - r.left) / (FloatHi) (rct.right - rct.left);
  2775.                    FormatText(0, &itemData, TRUE);
  2776.  
  2777.             if (pixels != 0)  r.top += itemData.leadHeight;
  2778.                 r.top += itemData.spaceBefore;
  2779.              
  2780.             visBelow = (r.bottom - r.top) / itemData.lineHeight;
  2781.             if ((itemData.keepTogether && visBelow < itemData.numRows) ||
  2782.                 itemData.newPage) {
  2783.               goOn = Nlm_EndPage ();
  2784.               if (goOn)  goOn = Nlm_StartPage ();
  2785.               newPage = FALSE;
  2786.               Nlm_PrintingRect (&r);
  2787.               visBelow = (r.bottom - r.top) / itemData.lineHeight;
  2788.                 }
  2789.             line = 0;
  2790.             while (visBelow + line < itemData.numRows && goOn) {
  2791.                   pixels = DrawStyledItem( &itemData, &r, item+1, line, TRUE, NULL);
  2792.               r.top += pixels;
  2793.                     r.top += itemData.spaceAfter;
  2794.               line += visBelow;
  2795.               goOn = Nlm_EndPage ();
  2796.               if (goOn) Nlm_StartPage ();
  2797.               newPage = FALSE;
  2798.               Nlm_PrintingRect (&r);
  2799.               visBelow = (r.bottom - r.top) / itemData.lineHeight;
  2800.                 }
  2801.             if (visBelow > 0 && goOn) {
  2802.                   pixels = DrawStyledItem( &itemData, &r, item+1, line, TRUE, NULL);
  2803.               r.top += pixels;
  2804.                     r.top += itemData.spaceAfter;
  2805.                 }
  2806.                
  2807.               }
  2808.             }
  2809.         item++;
  2810.         if (r.top >= r.bottom) {
  2811.           goOn = Nlm_EndPage ();
  2812.           newPage = TRUE;
  2813.             }
  2814.           }
  2815.       if ((!newPage) && goOn) 
  2816.         goOn = Nlm_EndPage ();
  2817.        
  2818.       Nlm_EndPrinting (w);
  2819.       for (i = 0; i < MAXFONTS; i++) {
  2820.         gFontHeights [i].font = NULL;
  2821.         gFontHeights [i].height = 0;
  2822.         }
  2823.         }
  2824.         }
  2825.     fIsVirtual= savevirt;
  2826.    
  2827. #else
  2828.     Nlm_Message(MSG_OK,"Printing is not yet defined for this window system");
  2829. #endif
  2830. }
  2831.  
  2832.  
  2833.  
  2834. void  DRichView::SetTabs( short theTabstops) 
  2835.     fTabCount= theTabstops;
  2836. }
  2837.  
  2838.  
  2839. #if 0
  2840. enum docFormats {
  2841.     kUnknownformat,
  2842.     kTextformat,
  2843.     kRTFformat,
  2844.     kPICTformat,
  2845.     kHTMLformat,
  2846.     kMaxDocformat
  2847.     };
  2848. #endif
  2849.  
  2850. void  DRichView::ShowFile( char* filename, Nlm_FonT font) 
  2851. {
  2852.     fDocFormat= DRichHandler::kUnknownformat;
  2853.     DRTFHandler rtfhandler( this, NULL);
  2854.     if ( rtfhandler.ProcessFile( filename) ) 
  2855.         fDocFormat= rtfhandler.Format();
  2856.     else {
  2857.         DPICTHandler picthandler( this, NULL);
  2858.         if ( picthandler.ProcessFile( filename) )
  2859.             fDocFormat= picthandler.Format();
  2860.         else  { 
  2861.           DGIFHandler gifhandler( this, NULL);
  2862.           if ( gifhandler.ProcessFile( filename) ) 
  2863.               fDocFormat= gifhandler.Format(); 
  2864.           else {
  2865.               DHTMLHandler htmlhandler( this, NULL);
  2866.               if ( htmlhandler.ProcessFile( filename) ) 
  2867.                   fDocFormat= htmlhandler.Format(); 
  2868.               else {
  2869. #if 1
  2870.                   DRichHandler texthandler( this, NULL);
  2871.                   if ( texthandler.ProcessFile( filename) ) 
  2872.                       fDocFormat= texthandler.Format(); 
  2873. #else
  2874.                 ShowTextFile( filename, font);
  2875.                   fDocFormat= DRichHandler::kTextformat; 
  2876. #endif
  2877.                   }
  2878.               }
  2879.           }
  2880.         }
  2881. }
  2882.  
  2883. void  DRichView::ShowDoc( char* doctext, ulong doclength) 
  2884. {
  2885.     if (!doctext) return;
  2886.     if (!doclength) doclength= StrLen( doctext);
  2887.     char*    docend= doctext + doclength;
  2888.     
  2889.     if (fDocFormat) switch (fDocFormat) {
  2890.     
  2891.         case DRichHandler::kTextformat: {
  2892.             DRichHandler texthandler( this, NULL);
  2893.             if ( texthandler.ProcessData( doctext, docend, true, doclength) ) return;
  2894.             }
  2895.             break;
  2896.  
  2897.         case DPICTHandler::kPICTformat: {
  2898.             DPICTHandler picthandler( this, NULL);
  2899.             if ( picthandler.ProcessData( doctext, docend, true, doclength) ) return;
  2900.             }
  2901.             break;
  2902.             
  2903.         case DGIFHandler::kGIFformat: {
  2904.           DGIFHandler gifhandler( this, NULL);
  2905.             if ( gifhandler.ProcessData( doctext, docend, true, doclength) ) return;
  2906.             }
  2907.             break;
  2908.  
  2909.         case DHTMLHandler::kHTMLformat: {
  2910.             DHTMLHandler htmlhandler( this, NULL);
  2911.             if ( htmlhandler.ProcessData( doctext, docend, true, doclength) ) return;
  2912.             }
  2913.             break;
  2914.  
  2915.         case DRTFHandler::kRTFformat: { 
  2916.             DRTFHandler rtfhandler( this, NULL);
  2917.             if ( rtfhandler.ProcessData( doctext, docend, true, doclength) ) return;
  2918.             }
  2919.             break;
  2920.         }
  2921.         
  2922.     fDocFormat= DRichHandler::kUnknownformat;
  2923.     
  2924.     DRTFHandler rtfhandler( this, NULL);
  2925.     if ( rtfhandler.ProcessData( doctext, docend, true, doclength) ) 
  2926.         fDocFormat= rtfhandler.Format();
  2927.     else {
  2928.         DPICTHandler picthandler( this, NULL);
  2929.         if ( picthandler.ProcessData( doctext, docend, true, doclength) )
  2930.             fDocFormat= picthandler.Format();
  2931.         else  { 
  2932.           DGIFHandler gifhandler( this, NULL);
  2933.           if ( gifhandler.ProcessData( doctext, docend, true, doclength) ) 
  2934.               fDocFormat= gifhandler.Format(); 
  2935.           else {
  2936.               DHTMLHandler htmlhandler( this, NULL);
  2937.               if ( htmlhandler.ProcessData( doctext, docend, true, doclength) ) 
  2938.                   fDocFormat= htmlhandler.Format(); 
  2939.               else {
  2940.                   DRichHandler texthandler( this, NULL);
  2941.                   if ( texthandler.ProcessData( doctext, docend, true, doclength) ) 
  2942.                       fDocFormat= texthandler.Format(); 
  2943.                   }
  2944.               }
  2945.           }
  2946.         }
  2947. }
  2948.  
  2949.  
  2950.  
  2951. void DRichView::ShowTextFile( char* filename, Nlm_FonT font)
  2952. {    
  2953.     DParagraph    para;
  2954.     DRichStyle    aStyle;
  2955.     if (font) aStyle.font= font;
  2956.     aStyle.last= true;
  2957.   ShowFileFancy( filename, ¶, &aStyle, 1);
  2958. }
  2959.  
  2960.  
  2961.  
  2962.  
  2963.  
  2964. void  DRichView::ShowFileFancy( char* filename, DParagraph* parFormat,  
  2965.                                                                 DRichStyle* styles, short nstyles, short tabStops) 
  2966. {
  2967.   char         ch;
  2968.   short       actual, cnt, leftOver;
  2969.   long         cntr;
  2970.   FILE         *fp;
  2971.   Nlm_RecT     r;
  2972.   Nlm_WindoW   tempPort;
  2973.   char      * text,  * txt;
  2974.   Nlm_FonT         font;
  2975. #ifdef COMP_MPW
  2976.   char*  p;
  2977. #endif
  2978. #if (defined(OS_DOS) || defined (OS_NT))
  2979.   char*  p;
  2980.   char*  q;
  2981. #endif
  2982.     DParagraph    para;
  2983.  
  2984.   if ( filename  && filename [0] != '\0') {
  2985.          fTabCount = tabStops;
  2986.     if (parFormat == NULL) parFormat = ¶
  2987.     Nlm_Reset (fPanel);
  2988.     tempPort = Nlm_SavePort (fPanel);
  2989.         ViewRect( r);
  2990.     if (styles) font= styles->font;
  2991.     if (font == NULL) font = Nlm_programFont; //Nlm_systemFont;
  2992.      
  2993.     text = (char*) MemNew (16000);
  2994.     if (text) {
  2995.       fp = FileOpen (filename, "r");
  2996.       if (fp) {
  2997.         leftOver = 0;
  2998.         cntr = FileLength (filename);
  2999.         cnt = (short) MIN (cntr, 15000L);
  3000.  
  3001.         while (cnt > 0 && cntr > 0) {
  3002.           txt = text + leftOver;
  3003.           actual = (short) FileRead (txt, 1, cnt, fp);
  3004.           if (actual > 0) {
  3005.             cnt = actual;
  3006.             txt [cnt] = '\0';
  3007.             ch = fgetc (fp);
  3008.             while (ch != '\0' && ch != '\n' && cnt < 15900) {
  3009.               txt [cnt] = ch;
  3010.               cnt++;
  3011.               ch = fgetc (fp);
  3012.                 }
  3013.             while ((ch == '\n' || ch == '\r') && cnt < 15900) {
  3014.               txt [cnt] = ch;
  3015.               cnt++;
  3016.               ch = fgetc (fp);
  3017.                 }
  3018.             txt [cnt] = '\0';
  3019. #if (defined(OS_DOS) || defined (OS_NT))
  3020.             p = text;
  3021.             q = text;
  3022.             while (*p) {
  3023.               if (*p == '\r') {
  3024.                 p++;
  3025.               } else {
  3026.                 *q = *p;
  3027.                 p++;
  3028.                 q++;
  3029.               }
  3030.             }
  3031.             *q = '\0';
  3032. #endif
  3033. #ifdef COMP_MPW
  3034.             p = text;
  3035.             while (*p) {
  3036.               if (*p == '\r') {
  3037.                 *p = '\n';
  3038.               }
  3039.               p++;
  3040.             }
  3041. #endif
  3042.             Append( text, parFormat, styles, nstyles, NULL); 
  3043.                 /* dgg -- need to fiddle w/ styles to match to subset of text !! */
  3044.             leftOver = 1;
  3045.             text [0] = ch;
  3046.             cntr -= cnt;
  3047.             cnt = (short) MIN (cntr, 15000L);
  3048.               } 
  3049.           else {
  3050.             cnt = 0;
  3051.             cntr = 0;
  3052.               }
  3053.             }
  3054.         FileClose (fp);
  3055.           }
  3056.       text = (char*) MemFree (text);
  3057.         }
  3058.     if (!fAutoAdjust) AdjustScroll();
  3059.     if (tempPort) Nlm_RestorePort (tempPort);
  3060.       }
  3061. }
  3062.  
  3063.  
  3064.  
  3065.         
  3066.     
  3067.     
  3068. void DRichView::DoubleClick(Nlm_PoinT mouse)
  3069. {
  3070.     short                 item, row, atch;
  3071.     Nlm_RecT        rct;
  3072.     char                wordAt[512];
  3073.     DRichStyle     * styleAt = NULL;
  3074.  
  3075.         // sickly demo
  3076.     wordAt[0]= 0;
  3077.     MapPoint( mouse, item, row, &rct, wordAt, 512, NULL/*styleAt*/);
  3078.     atch= gMapOfs;  
  3079.     SetSelectedText( item, atch, item, atch); 
  3080.     if (fMapStyle) {
  3081.         if (fMapStyle->ispict) {
  3082.             Nlm_PoinT atp;
  3083.             atp.x= mouse.x - fDrawr.left;
  3084.             atp.y= mouse.y - fDrawr.top;
  3085.             // if fMapStyle->ismap, do things w/ gopher link
  3086. #if 0
  3087.             Message(MSG_OK, "dblClik in picture x=%d y=%d, picwd=%d picht=%d", 
  3088.                     atp.x, atp.y, fMapStyle->pixwidth, fMapStyle->pixheight);
  3089. #endif
  3090.             }
  3091.         else {
  3092.             Nlm_InvertRect(&rct);
  3093. #if 0
  3094.             Message(MSG_OK, "dblClik text at prg=%d row=%d sto=%d '%s'",
  3095.                              item, row, fMapStyle->nextofs, wordAt);
  3096. #endif
  3097.             InvalRect( rct);
  3098.             }
  3099.         }
  3100.     //this->Select();
  3101.     this->GetWindow()->Select();
  3102. }
  3103.  
  3104. void DRichView::SingleClick(Nlm_PoinT mouse) 
  3105. {
  3106.     short             item, row, atch;
  3107.     Nlm_RecT        rct;
  3108.     char                wordAt[512];
  3109.  
  3110.     wordAt[0]= 0;
  3111.     MapPoint( mouse, item, row, &rct, wordAt, 512, NULL/*styleAt*/);
  3112.     atch= gMapOfs;  
  3113.         SetSelectedText( item, atch, item, atch); 
  3114. }
  3115.  
  3116. void DRichView::Click(Nlm_PoinT mouse)
  3117. {
  3118.     ClearCurrentStyle(); // Vibrant click calls change FONT !!
  3119.     if (Nlm_dblClick) DoubleClick( mouse);
  3120.     else SingleClick(mouse);        
  3121. }
  3122.     
  3123. void  DRichView::SetAutoAdjust( Boolean autoAdjust) 
  3124. {
  3125.     fAutoAdjust= autoAdjust;
  3126. }
  3127.  
  3128.  
  3129. #if 0
  3130. void DRichView::Show()
  3131. {
  3132.   Nlm_Update(); //!? need since took out vibwnds autoupdate for RestorePort
  3133. }
  3134. #endif
  3135.  
  3136. // this is DPanel form:
  3137. //void DRichView::Scroll( Boolean vertical, DView* scrollee, short newval, short oldval)
  3138.  
  3139. void DRichView::ScrollDoc(Nlm_BaR sb, short newval, short oldval)
  3140. {
  3141.         // Scroll bar callback that takes suppressed partial lines into account
  3142.         // this is good only for vertical==true
  3143.   Boolean      goToEnd;
  3144.   short     barmax, barval, firstShown;
  3145.   short     height,highest,highFree,item, lo1, hi1;
  3146.   short     line, lineInto,lowest,lowFree;
  3147.   short     pixels,pgDn,pgUp,vis;
  3148.   Nlm_RecT     r;
  3149.   DParagraph*  itemPtr;
  3150.     
  3151.     // Nlm_SlatE s= (Nlm_SlatE) fPanel;
  3152.     
  3153.   if (oldval != newval) {
  3154.     if (Nlm_Visible (fPanel) && Nlm_AllParentsVisible (fPanel)) {
  3155.             ViewRect( r);
  3156.       height = r.bottom - r.top;
  3157.       item = GetItemNum ( newval);
  3158.       line = newval - GetLineStart( item);
  3159.       firstShown = item;
  3160.       lineInto = line;
  3161.       lowest = INT2_MAX;
  3162.       highest = INT2_MIN;
  3163.       pgUp = VisLinesAbove ( &r, item, line, lowest, highest) - 1;
  3164.       pgDn = VisLinesBelow ( &r, item, line, lowest, highest) - 1;
  3165.       if (pgDn < 1)  pgDn = 1;
  3166.       if (pgUp < 1)  pgUp = 1;
  3167.       if (lowest < INT2_MAX)  
  3168.         fNumLines = UpdateLineStarts ( lowest);
  3169.       Nlm_Select (fPanel);
  3170.       if ((newval > oldval && newval - pgUp <= oldval) ||
  3171.           (newval < oldval && newval + pgDn >= oldval)) {
  3172.         pixels = PixelsBetween ( &r, newval, oldval, lo1, hi1);
  3173.         if (ABS (pixels) < height) {
  3174.           Nlm_ScrollRect (&r, 0, pixels);
  3175.           if (pixels<0) r.top = r.bottom + pixels; // - 5;
  3176.           else r.bottom = r.top + pixels; // + 5;
  3177.           Nlm_InsetRect (&r, -1, -1);
  3178.           Nlm_InvalRect (&r);
  3179.             } 
  3180.         else {
  3181.           Nlm_InsetRect (&r, -1, -1);
  3182.           Nlm_InvalRect (&r);
  3183.             }
  3184.           } 
  3185.       else {
  3186.         Nlm_InsetRect (&r, -1, -1);
  3187.         Nlm_InvalRect (&r);
  3188.           }
  3189.       lowFree = INT2_MAX;
  3190.       highFree = INT2_MIN;
  3191.       for (item = 0; item < lowest; item++)  
  3192.         FreeCachedItem ( item, lowFree, highFree);
  3193.       for (item = highest + 1; item < fNumItems; item++) 
  3194.         FreeCachedItem ( item, lowFree, highFree);
  3195.       if (lowFree < INT2_MAX) 
  3196.         fNumLines = UpdateLineStarts ( lowFree);
  3197.       
  3198.       barmax = 0;
  3199.       goToEnd = (Boolean) (newval == fBarmax);
  3200.       if (fNumLines > 0 && fNumItems > 0) {
  3201.         itemPtr = GetParaPtr( fNumItems - 1);
  3202.         if (itemPtr) {
  3203.                     ViewRect( r);
  3204.           lowest = INT2_MAX;
  3205.           highest = INT2_MIN;
  3206.           vis = VisLinesAbove ( &r, fNumItems - 1,
  3207.                                itemPtr->numRows - 1, lowest, highest);
  3208.           if (lowest < INT2_MAX)  
  3209.             fNumLines = UpdateLineStarts ( lowest);
  3210.           barmax = fNumLines - vis;
  3211.             }
  3212.           }
  3213.       barval = GetLineStart( firstShown) + lineInto;
  3214.       if (goToEnd) barval = barmax;
  3215.     
  3216.       if (barval > fBarmax) {
  3217.         Nlm_CorrectBarMax (sb, barmax);
  3218.         Nlm_CorrectBarValue (sb, barval);
  3219.           } 
  3220.       else {
  3221.         Nlm_CorrectBarValue (sb, barval);
  3222.         Nlm_CorrectBarMax (sb, barmax);
  3223.           }
  3224.       Nlm_CorrectBarPage (sb, pgUp, pgDn);
  3225.       fBarmax = barmax;
  3226.       Nlm_Update ();
  3227.     }
  3228.   }
  3229. }
  3230.  
  3231.  
  3232.  
  3233. // Performs garbage collection on document data
  3234.  
  3235. void DRichView::ResetDoc()
  3236. {
  3237.     DeleteAll();
  3238.   fNumItems = 0;
  3239.   fNumLines = 0;
  3240.   fBarmax = 0;
  3241.   //DRichView::InitRichView();
  3242. }
  3243.  
  3244.  
  3245.  
  3246.  
  3247.  
  3248.  
  3249.  
  3250.  
  3251.  
  3252. // class DRichFindDialog
  3253.  
  3254. class DRichFindDialog : public DFindDialog {
  3255. public:
  3256.     DRichView* fView;
  3257.     char    * fLastTarget;
  3258.     short        fLastParag, fLastChar;
  3259.     DRichFindDialog(  DRichView* itsView);
  3260.     virtual void DoFind();
  3261.     virtual void BuildDlog();
  3262. };
  3263.  
  3264. DRichFindDialog::DRichFindDialog(  DRichView* itsView) :
  3265.         fView( itsView), fLastTarget(NULL),  fLastParag(-1), fLastChar(-1)
  3266. {
  3267. }
  3268.  
  3269.  
  3270. void DRichFindDialog::BuildDlog()
  3271. {
  3272.     DFindDialog::BuildDlog();
  3273.  
  3274.     DView* av;
  3275.     av= FindSubview(replaceId); if (av) { av->Disable(); } //av->Hide();
  3276.     av= FindSubview(replaceFindId); if (av) { av->Disable();  }
  3277.     av= FindSubview(replaceAllId); if (av) { av->Disable(); }
  3278.     av= FindSubview(cBackwards);     if (av) { av->Disable(); }
  3279.     av= FindSubview(cFullWord); if (av) { av->Disable(); }
  3280.     //av= FindSubview(cCaseSense); if (av) { av->Disable(); }
  3281.     if (fReplaceText) fReplaceText->Disable();
  3282. }
  3283.  
  3284. void DRichFindDialog::DoFind() 
  3285. {
  3286.     const char    *target;
  3287.     Boolean     casesense, back, fullword, found;
  3288.     short            paragat, charat;
  3289.     long            len;
  3290.     
  3291.     target= this->GetFind();
  3292.     if (target && *target) {
  3293.         casesense    = this->CaseSensitive();
  3294.         back= this->Backwards();         // not yet supported
  3295.         fullword= this->FullWord(); // not yet supported
  3296.         paragat= fView->fSelParag - 1; // offset by -1 for real parag# -- MESS !
  3297.         charat= fView->fSelChar;
  3298.         len= StrLen(target);
  3299.         if (fLastTarget && StringCmp(target, fLastTarget)==0 
  3300.          && paragat == fLastParag && charat == fLastChar) {
  3301.             charat += len;
  3302.             found= fView->Find( (char*)target, paragat, charat, paragat, charat, casesense); 
  3303.             }
  3304.         else {
  3305.             if (fLastTarget) MemFree(fLastTarget);
  3306.             fLastTarget= StrDup(target);
  3307.             found= fView->Find( (char*)target, paragat, charat, paragat, charat, casesense); 
  3308.             }
  3309.         fLastParag= paragat;
  3310.         fLastChar = charat;
  3311.         if (found) {
  3312.             fView->SetSelectedText( paragat+1, charat, paragat+1, charat + len);
  3313.             }
  3314.         }
  3315. }                
  3316.  
  3317.  
  3318.  
  3319. //class    DRichTextDoc : public DWindow
  3320.  
  3321.  
  3322.  
  3323. Nlm_RecT DRichTextDoc::gRichDocRect = { 0, 0, 0, 0 };
  3324.  
  3325.  
  3326. DRichTextDoc::DRichTextDoc( long id, Boolean makeRichView, Nlm_FonT itsFont) :
  3327.         DWindow( id, gApplication, document),
  3328.         fRichView(NULL), fFloatingEditText(NULL)
  3329. {     
  3330.     Nlm_PoinT nps;
  3331.     fFont= itsFont;
  3332.     this->GetNextPosition( &nps);
  3333.     fFloatingEditText= (DDialogText*) new DHiddenText(0,this,"");
  3334.     this->SetNextPosition( nps);
  3335.     fFloatingEditText->Hide();
  3336.     //this->SetEditText(fFloatingEditText);
  3337.     
  3338.     if (makeRichView) {
  3339.         this->GetNextPosition( &nps);
  3340.         nps.x= 0; // fix for odd offset
  3341.         this->SetNextPosition( nps);
  3342.         fRichView= new DRichView( 0, this, gPrintManager->PageWidth(), 0);
  3343.         fRichView->SetSlateBorder( true);
  3344.         fRichView->SetResize( DView::matchsuper, DView::relsuper);
  3345.         //fRichView->SetTabs( gTextTabStops);
  3346.         //fRichView->SizeToSuperview( fWindow, true, false); // this needs to adjust for if view has scrollbar !
  3347.         //fSaveHandler= fRichView; //DRichView() installs these handlers !
  3348.         //fPrintHandler= fRichView;
  3349.         }
  3350. }
  3351.  
  3352.                               
  3353. void DRichTextDoc::Open()
  3354. {
  3355.     this->CalcWindowSize();
  3356.     if (!fFindDlog) fFindDlog= new DRichFindDialog( fRichView);
  3357.     fRichView->SizeToSuperview( this, true, false); // this needs to adjust for if view has scrollbar !
  3358.     DWindow::Open();
  3359. }
  3360.  
  3361. void DRichTextDoc::OpenText( char* doctext, ulong doclength)
  3362. {
  3363.     if (doctext) {
  3364.         fRichView->ShowDoc( doctext, doclength);
  3365.         Open();
  3366.         }
  3367. }
  3368.  
  3369.  
  3370. void DRichTextDoc::Open( DFile* aFile)
  3371. {
  3372.     if (aFile) {
  3373.         SetTitle( (char*)aFile->GetShortname());
  3374.         SetFilename( (char*)aFile->GetName());
  3375.         fRichView->ShowFile( (char*)aFile->GetName(), fFont);
  3376.         }
  3377.     Open();
  3378. }
  3379.  
  3380. void  DRichTextDoc::Open( char* filename) 
  3381. {
  3382.     SetTitle( (char*)DFileManager::FilenameFromPath(filename));
  3383.     SetFilename( (char*) filename);
  3384.     fRichView->ShowFile( filename, fFont);
  3385.   Open();
  3386. }
  3387.  
  3388. void DRichTextDoc::Close()
  3389. {
  3390.     //if (!Nlm_EmptyRect(&fViewrect)) gRichDocRect= fViewrect;  
  3391.     if (fRichView) fRichView->ViewRect( gRichDocRect);  // GetPosition
  3392.     DWindow::Close();
  3393. }
  3394.  
  3395. void DRichTextDoc::ResizeWin()
  3396. {
  3397.     DWindow::ResizeWin();
  3398.     if (fRichView) fRichView->ViewRect( gRichDocRect);
  3399.     //if (!Nlm_EmptyRect(&fViewrect)) gRichDocRect= fViewrect;  
  3400. }
  3401.  
  3402. Boolean DRichTextDoc::IsMyAction(DTaskMaster* action) 
  3403. {
  3404.     switch(action->Id()) {
  3405.         case DApplication::kUndo:
  3406.             Message(MSG_OK,"DRichTextDoc::Undo not ready.");
  3407.             return true;
  3408.         case DApplication::kCut:
  3409.             Message(MSG_OK,"DRichTextDoc::Cut not ready.");
  3410.             //this->CutText(); 
  3411.             return true;
  3412.             
  3413.         case DApplication::kCopy: {
  3414.             char* theText= NULL;
  3415.             if (fRichView) theText= fRichView->GetSelectedText();
  3416.             if (theText) {
  3417.                 fFloatingEditText->SetText(theText);
  3418.                 fFloatingEditText->SetSelection(0,32000); 
  3419.           fFloatingEditText->CopyText(); 
  3420.           MemFree( theText);
  3421.                 fFloatingEditText->SetText(""); // don't need to keep extra copies around
  3422.                 //Message(MSG_OK,"DRichTextDoc::Copied text selection.");
  3423.           }
  3424.         }
  3425.             return true;
  3426.             
  3427.         case DApplication::kPaste:
  3428.             Message(MSG_OK,"DRichTextDoc::Paste not ready.");
  3429.             //this->PasteText(); 
  3430.             return true;
  3431.         case DApplication::kClear:
  3432.             Message(MSG_OK,"DRichTextDoc::Clear not ready.");
  3433.             //this->ClearText(); 
  3434.             return true;
  3435.         case DApplication::kSelectAll:
  3436.             //Message(MSG_OK,"DRichTextDoc::Select all not ready.");
  3437.             if (fRichView) fRichView->SelectAll();
  3438.             //this->SetSelection(0,0,32000,32000); 
  3439.             return true;
  3440.         default:
  3441.             return DWindow::IsMyAction(action);
  3442.         }
  3443. }
  3444.  
  3445.  
  3446. // class DRichApplication : public DApplication
  3447.  
  3448.  
  3449. DRichApplication::DRichApplication()
  3450. {
  3451.     //fAcceptableFileTypes= "TEXTPICTGIFfRTF "; /* up to 4 types, or null for all types */
  3452.     // ^^ not working, only 1st seen !?
  3453.     //fAcceptableFileTypes= NULL;
  3454. }
  3455.  
  3456.  
  3457. void DRichApplication::OpenDocument(DFile* aFile)
  3458. {
  3459.     if (aFile && aFile->Exists()) {
  3460.         gCursor->watch();
  3461.         DRichTextDoc* aDoc= new DRichTextDoc();
  3462.         aDoc->Open( aFile);
  3463.         gCursor->arrow();
  3464.         }
  3465. }
  3466.  
  3467.  
  3468.